@liquidcars/atlas-geometry-math 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +56 -2
- package/catalog.js +205 -0
- package/index.js +9 -0
- package/package.json +52 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Atlas contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,57 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @liquidcars/atlas-geometry-math
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Matemáticas en vóxeles para LiquidCars Atlas. Primera versión: `0.1.0`.
|
|
4
|
+
|
|
5
|
+
## Uso en Atlas
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
import '@liquidcars/atlas';
|
|
9
|
+
import '@liquidcars/atlas-geometry-math';
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```yaml
|
|
13
|
+
- id: example
|
|
14
|
+
name: Hito del conocimiento
|
|
15
|
+
geometry: math.euclid-elements
|
|
16
|
+
geometryOptions:
|
|
17
|
+
accent: "#8bbce7"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
El punto de entrada raíz registra automáticamente el paquete mediante `registerGeometryPack`. Incluye catálogo, etiquetas, tamaños canónicos, parámetros y un `showcase`. Compatible y probado con `@liquidcars/atlas` **0.1.52**; la dependencia par se limita a la serie 0.1. La dependencia es opcional para consumidores de descriptores, pero Atlas debe estar instalado cuando se importa la raíz que registra el paquete.
|
|
21
|
+
|
|
22
|
+
## Uso sin Atlas ni Three.js
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import {mathGeometryPack} from '@liquidcars/atlas-geometry-math/catalog';
|
|
26
|
+
const geometry = mathGeometryPack.geometries.find(g => g.id === 'euclid-elements');
|
|
27
|
+
const {parts} = geometry.create({parameters: {accent: '#8bbce7'}});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
El catálogo es ESM y no necesita DOM, WebGL ni un motor 3D. Cada pieza declara `shape: box`, `size`, `position`, `rotation` (Euler XYZ en radianes), `color` y propiedades de material. Cada llamada crea datos independientes. El juego agrupa estas piezas mediante `InstancedMesh`; Atlas consume el mismo descriptor.
|
|
31
|
+
|
|
32
|
+
`accent` está disponible en las figuras que utilizan un color principal configurable. Las demás conservan su paleta representativa.
|
|
33
|
+
|
|
34
|
+
`canonicalSize` mantiene las proporciones de la figura, incluido su pedestal predeterminado. Las geometrías son interpretaciones visuales originales: no reconstrucciones exactas, reproducciones de pinturas ni afirmaciones de autoría histórica. Las fichas, fechas, preguntas y premios pertenecen a la aplicación consumidora.
|
|
35
|
+
|
|
36
|
+
## Desarrollo
|
|
37
|
+
|
|
38
|
+
Desde la raíz del repositorio:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
npm ci
|
|
42
|
+
npm test
|
|
43
|
+
npm run build:geometry
|
|
44
|
+
npm pack --workspace=@liquidcars/atlas-geometry-math
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
La publicación se hace desde el workspace, después de decidir visibilidad y validar el tarball. Los archivos construidos contienen los auxiliares comunes; no dependen de un tercer paquete interno ni de rutas del repositorio. Licencia MIT.
|
|
48
|
+
|
|
49
|
+
## Catálogo
|
|
50
|
+
|
|
51
|
+
| Identificador | Nombre |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `math.plimpton-tablet` | Triángulos en arcilla |
|
|
54
|
+
| `math.rhind-papyrus` | Problemas sobre papiro |
|
|
55
|
+
| `math.pythagoras-triangle` | Triángulo rectángulo |
|
|
56
|
+
| `math.euclid-elements` | Elementos de Euclides |
|
|
57
|
+
| `math.apollonius-conics` | Cónicas de Apolonio |
|
package/catalog.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// packages/shared/voxel-parts.js
|
|
2
|
+
function voxelBuilder(accent = "#8bbce7") {
|
|
3
|
+
const parts = [], ivory = "#eee9d0", metal = "#bd9c66", blue = "#85cee4", red = "#e58b82", green = "#8bc88c", gold = "#f1cd75", dark = "#30465c";
|
|
4
|
+
const block = (w, h, d, color, x, y, z, rotation = [0, 0, 0]) => parts.push({ shape: "box", size: [w, h, d], position: [x, y, z], rotation, color, edges: false, roughness: 0.72 });
|
|
5
|
+
function rod(a, b, size, color) {
|
|
6
|
+
const delta = b.map((v, i) => v - a[i]), length = Math.hypot(...delta);
|
|
7
|
+
if (!length) return;
|
|
8
|
+
const [dx, dy, dz] = delta.map((v) => v / length);
|
|
9
|
+
let x = dz, y = 0, z = -dx, w = 1 + dy;
|
|
10
|
+
if (w < 1e-12) {
|
|
11
|
+
x = 0;
|
|
12
|
+
y = 0;
|
|
13
|
+
z = 1;
|
|
14
|
+
w = 0;
|
|
15
|
+
}
|
|
16
|
+
const n = Math.hypot(x, y, z, w);
|
|
17
|
+
x /= n;
|
|
18
|
+
y /= n;
|
|
19
|
+
z /= n;
|
|
20
|
+
w /= n;
|
|
21
|
+
const m13 = 2 * (x * z + y * w), pitch = Math.asin(Math.max(-1, Math.min(1, m13)));
|
|
22
|
+
const rotation = Math.abs(m13) < 0.9999999 ? [Math.atan2(-2 * (y * z - x * w), 1 - 2 * (x * x + y * y)), pitch, Math.atan2(-2 * (x * y - z * w), 1 - 2 * (y * y + z * z))] : [Math.atan2(2 * (y * z + x * w), 1 - 2 * (x * x + z * z)), pitch, 0];
|
|
23
|
+
const c = a.map((v, i) => (v + b[i]) / 2);
|
|
24
|
+
block(size, length, size, color, ...c, rotation);
|
|
25
|
+
}
|
|
26
|
+
function loop(cx, cy, cz, rx, ry, color, plane = "xz", steps = 20) {
|
|
27
|
+
for (let i = 0; i < steps; i++) {
|
|
28
|
+
const a = i * Math.PI * 2 / steps, u = Math.cos(a) * rx, v = Math.sin(a) * ry;
|
|
29
|
+
block(0.095, 0.095, 0.095, color, cx + u, cy + (plane === "xy" ? v : 0), cz + (plane === "xz" ? v : 0));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function ball(x, y, z, color, r = 0.26) {
|
|
33
|
+
const step = 0.16;
|
|
34
|
+
for (let i = -2; i <= 2; i++) for (let j = -2; j <= 2; j++) for (let k = -2; k <= 2; k++) if (Math.hypot(i * step, j * step, k * step) <= r + 0.025) block(step * 0.93, step * 0.93, step * 0.93, color, x + i * step, y + j * step, z + k * step);
|
|
35
|
+
}
|
|
36
|
+
function book(x = 0, y = 0.52, z = 0) {
|
|
37
|
+
block(1.45, 0.13, 1.05, accent, x, y - 0.06, z);
|
|
38
|
+
block(0.66, 0.14, 0.93, ivory, x - 0.35, y + 0.06, z);
|
|
39
|
+
block(0.66, 0.14, 0.93, ivory, x + 0.35, y + 0.06, z);
|
|
40
|
+
block(0.04, 0.18, 0.98, metal, x, y + 0.07, z);
|
|
41
|
+
}
|
|
42
|
+
function flask(x, y, z, color = blue) {
|
|
43
|
+
for (const [yy, w] of [[0, 0.65], [0.2, 0.86], [0.4, 0.65]]) {
|
|
44
|
+
block(0.1, 0.23, 0.55, color, x - w / 2, y + yy, z);
|
|
45
|
+
block(0.1, 0.23, 0.55, color, x + w / 2, y + yy, z);
|
|
46
|
+
}
|
|
47
|
+
block(0.68, 0.1, 0.55, color, x, y - 0.1, z);
|
|
48
|
+
block(0.5, 0.22, 0.45, gold, x, y + 0.04, z);
|
|
49
|
+
}
|
|
50
|
+
block(2.65, 0.18, 2.2, dark, 0, 0.22, 0);
|
|
51
|
+
return { parts, block, rod, loop, ball, book, flask, accent, ivory, metal, blue, red, green, gold, dark };
|
|
52
|
+
}
|
|
53
|
+
function partsSize(parts) {
|
|
54
|
+
const min = [Infinity, Infinity, Infinity], max = [-Infinity, -Infinity, -Infinity];
|
|
55
|
+
for (const p of parts) {
|
|
56
|
+
const [rx, ry, rz] = p.rotation || [0, 0, 0], cx = Math.cos(rx), sx = Math.sin(rx), cy = Math.cos(ry), sy = Math.sin(ry), cz = Math.cos(rz), sz = Math.sin(rz);
|
|
57
|
+
for (const a of [-1, 1]) for (const b of [-1, 1]) for (const c of [-1, 1]) {
|
|
58
|
+
const [x, y, z] = [p.size[0] * a / 2, p.size[1] * b / 2, p.size[2] * c / 2];
|
|
59
|
+
const x1 = cz * x - sz * y, y1 = sz * x + cz * y;
|
|
60
|
+
const x2 = cy * x1 + sy * z, z2 = -sy * x1 + cy * z;
|
|
61
|
+
const v = [x2, cx * y1 - sx * z2, sx * y1 + cx * z2].map((n, i) => n + p.position[i]);
|
|
62
|
+
for (let i = 0; i < 3; i++) {
|
|
63
|
+
min[i] = Math.min(min[i], v[i]);
|
|
64
|
+
max[i] = Math.max(max[i], v[i]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return max.map((v, i) => v - min[i]);
|
|
69
|
+
}
|
|
70
|
+
function defineVoxelGeometry(build, { id, kind, name, description, tags = [], accent = "#8bbce7", collection = "Conceptos" }) {
|
|
71
|
+
const initial = build(kind, { accent }), usesAccent = initial.some((part) => part.color === accent);
|
|
72
|
+
return {
|
|
73
|
+
id,
|
|
74
|
+
name,
|
|
75
|
+
description,
|
|
76
|
+
tags,
|
|
77
|
+
collection,
|
|
78
|
+
canonicalSize: partsSize(initial),
|
|
79
|
+
parameters: usesAccent ? { accent: { type: "color", label: "Color principal", default: accent } } : {},
|
|
80
|
+
create({ parameters = {}, colors = {} } = {}) {
|
|
81
|
+
return { parts: build(kind, { accent: parameters.accent || colors.accent || accent }) };
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// packages/atlas-geometry-math/src/catalog.js
|
|
87
|
+
function buildMathParts(kind, { accent = "#8bbce7" } = {}) {
|
|
88
|
+
const { parts, block, rod, loop, ball, book, ivory, metal, blue, red, green, gold, dark } = voxelBuilder(accent);
|
|
89
|
+
switch (kind) {
|
|
90
|
+
case "tablet": {
|
|
91
|
+
block(1.9, 1.35, 0.3, metal, 0, 1.12, 0);
|
|
92
|
+
for (let row = 0; row < 4; row++) for (let col = 0; col < 5; col++) {
|
|
93
|
+
block(0.15, 0.045, 0.05, dark, -0.7 + col * 0.33, 0.67 + row * 0.28, 0.18);
|
|
94
|
+
block(0.04, 0.12, 0.05, ivory, -0.66 + col * 0.33, 0.69 + row * 0.28, 0.19);
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case "scroll": {
|
|
99
|
+
block(1.6, 0.1, 1.25, ivory, 0, 0.5, 0);
|
|
100
|
+
for (const x of [-0.85, 0.85]) rod([x, 0.65, -0.7], [x, 0.65, 0.7], 0.25, gold);
|
|
101
|
+
for (let i = 0; i < 6; i++) block(0.9, 0.04, 0.045, metal, 0, 0.57, -0.45 + i * 0.18);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case "triangles": {
|
|
105
|
+
rod([-0.9, 0.5, 0], [-0.9, 2, 0], 0.12, blue);
|
|
106
|
+
rod([-0.9, 0.5, 0], [0.9, 0.5, 0], 0.12, gold);
|
|
107
|
+
rod([-0.9, 2, 0], [0.9, 0.5, 0], 0.12, accent);
|
|
108
|
+
block(0.25, 0.07, 0.1, ivory, -0.75, 0.75, 0);
|
|
109
|
+
block(0.07, 0.25, 0.1, ivory, -0.62, 0.62, 0);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case "geometry": {
|
|
113
|
+
loop(0, 1.2, 0, 0.92, 0.92, accent, "xy", 28);
|
|
114
|
+
rod([-0.92, 1.2, 0], [0.92, 1.2, 0], 0.09, gold);
|
|
115
|
+
rod([0, 0.4, 0.5], [0.5, 1.7, 0.5], 0.1, metal);
|
|
116
|
+
rod([0.5, 1.7, 0.5], [0.95, 0.4, 0.5], 0.1, metal);
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case "conics": {
|
|
120
|
+
for (let i = 0; i < 7; i++) {
|
|
121
|
+
const radius = 0.82 - i * 0.1;
|
|
122
|
+
loop(0, 0.6 + i * 0.21, 0, radius, radius, i === 3 ? accent : ivory, "xz", 16);
|
|
123
|
+
}
|
|
124
|
+
loop(0, 1.23, 0, 0.62, 0.32, gold, "xz", 20);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
default:
|
|
128
|
+
throw new RangeError("Unknown math geometry: " + kind);
|
|
129
|
+
}
|
|
130
|
+
return parts;
|
|
131
|
+
}
|
|
132
|
+
var entries = [
|
|
133
|
+
{
|
|
134
|
+
"id": "plimpton-tablet",
|
|
135
|
+
"kind": "tablet",
|
|
136
|
+
"name": "Tri\xE1ngulos en arcilla",
|
|
137
|
+
"description": "Tablilla matem\xE1tica de la tradici\xF3n babil\xF3nica.",
|
|
138
|
+
"tags": [
|
|
139
|
+
"matem\xE1ticas",
|
|
140
|
+
"Babilonia",
|
|
141
|
+
"tablillas"
|
|
142
|
+
],
|
|
143
|
+
"accent": "#8bbce7",
|
|
144
|
+
"collection": "Hitos del conocimiento"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"id": "rhind-papyrus",
|
|
148
|
+
"kind": "scroll",
|
|
149
|
+
"name": "Problemas sobre papiro",
|
|
150
|
+
"description": "Papiro de la tradici\xF3n matem\xE1tica egipcia.",
|
|
151
|
+
"tags": [
|
|
152
|
+
"matem\xE1ticas",
|
|
153
|
+
"Egipto",
|
|
154
|
+
"papiros"
|
|
155
|
+
],
|
|
156
|
+
"accent": "#8bbce7",
|
|
157
|
+
"collection": "Hitos del conocimiento"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"id": "pythagoras-triangle",
|
|
161
|
+
"kind": "triangles",
|
|
162
|
+
"name": "Tri\xE1ngulo rect\xE1ngulo",
|
|
163
|
+
"description": "Tri\xE1ngulo y comparaci\xF3n de sus lados.",
|
|
164
|
+
"tags": [
|
|
165
|
+
"matem\xE1ticas",
|
|
166
|
+
"geometr\xEDa",
|
|
167
|
+
"Pit\xE1goras"
|
|
168
|
+
],
|
|
169
|
+
"accent": "#8bbce7",
|
|
170
|
+
"collection": "Hitos del conocimiento"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "euclid-elements",
|
|
174
|
+
"kind": "geometry",
|
|
175
|
+
"name": "Elementos de Euclides",
|
|
176
|
+
"description": "C\xEDrculo, di\xE1metro y comp\xE1s geom\xE9trico.",
|
|
177
|
+
"tags": [
|
|
178
|
+
"matem\xE1ticas",
|
|
179
|
+
"geometr\xEDa",
|
|
180
|
+
"Euclides"
|
|
181
|
+
],
|
|
182
|
+
"accent": "#8bbce7",
|
|
183
|
+
"collection": "Hitos del conocimiento"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"id": "apollonius-conics",
|
|
187
|
+
"kind": "conics",
|
|
188
|
+
"name": "C\xF3nicas de Apolonio",
|
|
189
|
+
"description": "Cono y sus secciones curvas.",
|
|
190
|
+
"tags": [
|
|
191
|
+
"matem\xE1ticas",
|
|
192
|
+
"geometr\xEDa",
|
|
193
|
+
"Apolonio"
|
|
194
|
+
],
|
|
195
|
+
"accent": "#8bbce7",
|
|
196
|
+
"collection": "Hitos del conocimiento"
|
|
197
|
+
}
|
|
198
|
+
];
|
|
199
|
+
var mathGeometryPack = { namespace: "math", name: "Matem\xE1ticas en v\xF3xeles", version: "0.1.0", category: "Matem\xE1ticas", palette: { accent: "#8bbce7" }, showcase: { groups: [{ id: "knowledge", name: "Hitos del conocimiento", items: entries.map((e) => ({ id: e.id, name: e.name, geometry: e.id })) }] }, geometries: entries.map((entry) => defineVoxelGeometry(buildMathParts, entry)) };
|
|
200
|
+
var mathModelIds = Object.freeze(Object.fromEntries(entries.map(({ kind, id }) => [kind, id])));
|
|
201
|
+
export {
|
|
202
|
+
buildMathParts,
|
|
203
|
+
mathGeometryPack,
|
|
204
|
+
mathModelIds
|
|
205
|
+
};
|
package/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// packages/atlas-geometry-math/src/index.js
|
|
2
|
+
import { registerGeometryPack } from "@liquidcars/atlas";
|
|
3
|
+
import { mathGeometryPack } from "./catalog.js";
|
|
4
|
+
export * from "./catalog.js";
|
|
5
|
+
registerGeometryPack(mathGeometryPack);
|
|
6
|
+
var index_default = mathGeometryPack;
|
|
7
|
+
export {
|
|
8
|
+
index_default as default
|
|
9
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liquidcars/atlas-geometry-math",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Mathematics voxel geometry pack for LiquidCars Atlas",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.js",
|
|
7
|
+
"module": "./index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.js",
|
|
10
|
+
"./catalog": "./catalog.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"index.js",
|
|
14
|
+
"catalog.js",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": [
|
|
19
|
+
"./index.js"
|
|
20
|
+
],
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@liquidcars/atlas": ">=0.1.52 <0.2.0"
|
|
23
|
+
},
|
|
24
|
+
"peerDependenciesMeta": {
|
|
25
|
+
"@liquidcars/atlas": {
|
|
26
|
+
"optional": true
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "node ../../scripts/build-geometry-packs.mjs",
|
|
34
|
+
"prepack": "node ../../scripts/build-geometry-packs.mjs"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"liquidcars",
|
|
38
|
+
"atlas",
|
|
39
|
+
"3d",
|
|
40
|
+
"geometry-pack",
|
|
41
|
+
"math",
|
|
42
|
+
"voxel"
|
|
43
|
+
],
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/gaelibus/atlas-game.git",
|
|
48
|
+
"directory": "packages/atlas-geometry-math"
|
|
49
|
+
},
|
|
50
|
+
"homepage": "https://github.com/gaelibus/atlas-game#readme",
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/gaelibus/atlas-game/issues"
|
|
53
|
+
}
|
|
54
|
+
}
|