@pixel-normal-edit/mcp 2.1.0 → 2.2.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/clear-firebase.js +37 -0
- package/domains/art-tree/README.md +134 -0
- package/domains/art-tree/REORGANIZATION_PLAN.md +168 -0
- package/domains/art-tree/REORGANIZATION_SUMMARY.md +260 -0
- package/domains/art-tree/index.js +58 -58
- package/domains/art-tree/lessons/3d/box-properties.js +38 -0
- package/domains/art-tree/lessons/3d/cone-properties.js +31 -0
- package/domains/art-tree/lessons/3d/cylinder-properties.js +29 -0
- package/domains/art-tree/lessons/3d/sphere-properties.js +25 -0
- package/domains/art-tree/lessons/advanced/angles.js +30 -0
- package/domains/art-tree/lessons/advanced/distances.js +26 -0
- package/domains/art-tree/lessons/advanced/shape-ratios.js +25 -0
- package/domains/art-tree/lessons/advanced/shape-relationships.js +28 -0
- package/domains/art-tree/lessons/advanced/symmetry-and-axis.js +26 -0
- package/domains/art-tree/{analysis_lessons.js → lessons/analysis/object-analysis.js} +5 -16
- package/domains/art-tree/lessons/basic/circles.js +26 -0
- package/domains/art-tree/lessons/basic/composition.js +34 -0
- package/domains/art-tree/lessons/basic/curves.js +31 -0
- package/domains/art-tree/lessons/basic/ellipses.js +26 -0
- package/domains/art-tree/lessons/basic/freehand.js +19 -0
- package/domains/art-tree/lessons/basic/index.js +36 -0
- package/domains/art-tree/lessons/basic/lines.js +38 -0
- package/domains/art-tree/lessons/basic/parallel-and-intersecting.js +22 -0
- package/domains/art-tree/lessons/basic/polygons.js +25 -0
- package/domains/art-tree/lessons/basic/proportions-and-angles.js +20 -0
- package/domains/art-tree/lessons/basic/spiral.js +21 -0
- package/domains/art-tree/lessons/basic/squares.js +28 -0
- package/domains/art-tree/lessons/basic/strokes.js +23 -0
- package/domains/art-tree/lessons/basic/triangles.js +30 -0
- package/domains/art-tree/lessons/cross-sections/bottle-sections.js +26 -0
- package/domains/art-tree/lessons/cross-sections/glass-sections.js +24 -0
- package/domains/art-tree/lessons/cross-sections/head-sections.js +17 -0
- package/domains/art-tree/lessons/curves/curve-properties.js +50 -0
- package/domains/art-tree/lessons/curves/curve-topology.js +45 -0
- package/domains/art-tree/lessons/curves/curve-types.js +44 -0
- package/domains/art-tree/lessons/ellipses/coaxial-ellipses.js +29 -0
- package/domains/art-tree/lessons/ellipses/ellipse-anatomy.js +26 -0
- package/domains/art-tree/lessons/ellipses/ellipse-orientations.js +28 -0
- package/domains/art-tree/lessons/ellipses/ellipse-proportions.js +27 -0
- package/domains/art-tree/lessons/hidden/hidden-box.js +20 -0
- package/domains/art-tree/lessons/hidden/hidden-cup.js +19 -0
- package/domains/art-tree/lessons/hidden/hidden-head.js +18 -0
- package/domains/art-tree/lessons/index.js +42 -0
- package/domains/art-tree/{layer_lessons.js → lessons/layers/layer-step.js} +5 -16
- package/domains/art-tree/lessons/lighting/contact-shadow.js +33 -0
- package/domains/art-tree/lessons/lighting/light-direction.js +30 -0
- package/domains/art-tree/lessons/lighting/light-zones.js +30 -0
- package/domains/art-tree/lessons/materials/material-glass.js +21 -0
- package/domains/art-tree/lessons/materials/material-shiny.js +26 -0
- package/domains/art-tree/lessons/materials/material-texture.js +26 -0
- package/domains/art-tree/lessons/perspective/1point-perspective.js +30 -0
- package/domains/art-tree/lessons/perspective/2point-perspective.js +30 -0
- package/domains/art-tree/lessons/perspective/3point-perspective.js +45 -0
- package/domains/art-tree/lessons/perspective/foreshortening.js +38 -0
- package/domains/art-tree/lessons/sky/sun-shapes.js +25 -0
- package/domains/art-tree/lessons/sky/sunset-colors.js +27 -0
- package/domains/art-tree/lessons/sky/sunset-sky.js +32 -0
- package/domains/art-tree/{structure_lessons.js → lessons/structure/axis-orientation.js} +3 -53
- package/domains/art-tree/lessons/structure/complex-structure.js +21 -0
- package/domains/art-tree/lessons/structure/x-yzaxes.js +28 -0
- package/domains/art-tree/lessons/surfaces/chair-analysis.js +17 -0
- package/domains/art-tree/lessons/surfaces/cup-analysis.js +18 -0
- package/domains/art-tree/lessons/surfaces/edge-types.js +40 -0
- package/domains/art-tree/lessons/surfaces/surface-types.js +42 -0
- package/domains/art-tree/lessons/transforms/bend.js +27 -0
- package/domains/art-tree/{transform_lessons_2.js → lessons/transforms/combine.js} +3 -54
- package/domains/art-tree/lessons/transforms/cut.js +25 -0
- package/domains/art-tree/lessons/transforms/hollow.js +24 -0
- package/domains/art-tree/lessons/transforms/rotate.js +16 -0
- package/domains/art-tree/lessons/transforms/squash.js +31 -0
- package/domains/art-tree/lessons/transforms/stretch.js +31 -0
- package/domains/art-tree/lessons/transforms/taper-swell.js +33 -0
- package/domains/art-tree/{vocab_lessons.js → lessons/vocab/vocab-house.js} +5 -16
- package/domains/art-tree/lib/tool-register.js +104 -0
- package/domains/art-tree/lib/validators.js +78 -0
- package/domains/art-tree/shapes/grid.js +37 -0
- package/domains/art-tree/shapes/polyline.js +26 -0
- package/domains/art-tree/{3d_tools.js → tools/3d.js} +2 -2
- package/domains/art-tree/{advanced_tools.js → tools/advanced.js} +2 -2
- package/domains/art-tree/{analysis_tools.js → tools/analysis.js} +2 -2
- package/domains/art-tree/{tools.js → tools/basic.js} +3 -3
- package/domains/art-tree/{cross_section_tools.js → tools/cross-sections.js} +2 -2
- package/domains/art-tree/{curve_tools.js → tools/curves.js} +2 -2
- package/domains/art-tree/{ellipse_tools.js → tools/ellipses.js} +2 -2
- package/domains/art-tree/{hidden_tools.js → tools/hidden.js} +2 -2
- package/domains/art-tree/tools/index.js +53 -0
- package/domains/art-tree/{layer_tools.js → tools/layers.js} +2 -2
- package/domains/art-tree/{light_tools.js → tools/lighting.js} +2 -2
- package/domains/art-tree/{material_tools.js → tools/materials.js} +2 -2
- package/domains/art-tree/{perspective_tools.js → tools/perspective.js} +2 -2
- package/domains/art-tree/{sky_tools.js → tools/sky.js} +2 -2
- package/domains/art-tree/{structure_tools.js → tools/structure.js} +2 -2
- package/domains/art-tree/{surface_tools.js → tools/surfaces.js} +2 -2
- package/domains/art-tree/{transform_tools.js → tools/transforms.js} +3 -3
- package/domains/art-tree/{vocab_tools.js → tools/vocab.js} +2 -2
- package/package.json +1 -1
- package/rules/prerequisites.js +30 -30
- package/rules/rules.js +1 -1
- package/rules/workflow.js +28 -20
- package/tools/canvas-tools.js +2 -2
- package/tools/drawing-tools.js +23 -12
- package/tools/workspace-tools.js +5 -4
- package/domains/art-tree/3d_lessons.js +0 -114
- package/domains/art-tree/advanced_lessons.js +0 -124
- package/domains/art-tree/cross_section_lessons.js +0 -65
- package/domains/art-tree/curve_lessons.js +0 -138
- package/domains/art-tree/ellipse_lessons.js +0 -105
- package/domains/art-tree/hidden_lessons.js +0 -55
- package/domains/art-tree/lessons.js +0 -305
- package/domains/art-tree/light_lessons.js +0 -92
- package/domains/art-tree/material_lessons.js +0 -71
- package/domains/art-tree/perspective_lessons.js +0 -138
- package/domains/art-tree/sky_lessons_1.js +0 -82
- package/domains/art-tree/surface_lessons.js +0 -112
- package/domains/art-tree/transform_lessons_1.js +0 -108
- /package/domains/art-tree/{3d_shapes.js → shapes/3d.js} +0 -0
- /package/domains/art-tree/{advanced_shapes.js → shapes/advanced.js} +0 -0
- /package/domains/art-tree/{analysis_shapes.js → shapes/analysis.js} +0 -0
- /package/domains/art-tree/{shapes.js → shapes/basic.js} +0 -0
- /package/domains/art-tree/{cross_section_shapes.js → shapes/cross-sections.js} +0 -0
- /package/domains/art-tree/{curve_shapes.js → shapes/curves.js} +0 -0
- /package/domains/art-tree/{ellipse_shapes.js → shapes/ellipses.js} +0 -0
- /package/domains/art-tree/{hidden_shapes.js → shapes/hidden.js} +0 -0
- /package/domains/art-tree/{layer_shapes.js → shapes/layers.js} +0 -0
- /package/domains/art-tree/{light_shapes.js → shapes/lighting.js} +0 -0
- /package/domains/art-tree/{material_shapes.js → shapes/materials.js} +0 -0
- /package/domains/art-tree/{perspective_shapes.js → shapes/perspective.js} +0 -0
- /package/domains/art-tree/{sky_shapes_1.js → shapes/sky.js} +0 -0
- /package/domains/art-tree/{structure_shapes.js → shapes/structure.js} +0 -0
- /package/domains/art-tree/{surface_shapes.js → shapes/surfaces.js} +0 -0
- /package/domains/art-tree/{transform_shapes.js → shapes/transforms.js} +0 -0
- /package/domains/art-tree/{vocab_shapes.js → shapes/vocab.js} +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from light_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Light Direction & Intensity (Light direction and plane values)
|
|
8
|
+
* Shows a box with planes facing/turning away from light.
|
|
9
|
+
*/
|
|
10
|
+
function lessonLightDirection(canvasSize = 32) {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx = Math.floor(canvasSize / 2);
|
|
13
|
+
const cy = Math.floor(canvasSize / 2);
|
|
14
|
+
const w = Math.floor(canvasSize * 0.25);
|
|
15
|
+
const h = Math.floor(canvasSize * 0.25);
|
|
16
|
+
|
|
17
|
+
// Light from top-left
|
|
18
|
+
const lightAngle = -Math.PI * 0.8;
|
|
19
|
+
|
|
20
|
+
const lx = cx - Math.floor(canvasSize * 0.35);
|
|
21
|
+
const ly = cy - Math.floor(canvasSize * 0.35);
|
|
22
|
+
commands.push(...lightShapes.drawLightSource(lx, ly, Math.floor(canvasSize * 0.05)));
|
|
23
|
+
|
|
24
|
+
// Draw shaded box
|
|
25
|
+
commands.push(...lightShapes.drawShadedBox(cx, cy, w, h, lightAngle));
|
|
26
|
+
|
|
27
|
+
return commands;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = { lessonLightDirection };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from light_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: 6 Zones of Light (Sphere)
|
|
8
|
+
* Highlight, Light, Halftone, Core shadow, Reflected light, Cast shadow.
|
|
9
|
+
*/
|
|
10
|
+
function lessonLightZones(canvasSize = 32) {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx = Math.floor(canvasSize / 2);
|
|
13
|
+
const cy = Math.floor(canvasSize / 2);
|
|
14
|
+
const r = Math.floor(canvasSize * 0.25);
|
|
15
|
+
|
|
16
|
+
// Light from top-left (approx -45 degrees or -135 degrees mathematically)
|
|
17
|
+
const lightAngle = -Math.PI * 0.75;
|
|
18
|
+
|
|
19
|
+
// Draw light source
|
|
20
|
+
const lx = cx + Math.floor(r * 2 * Math.cos(lightAngle));
|
|
21
|
+
const ly = cy + Math.floor(r * 2 * Math.sin(lightAngle));
|
|
22
|
+
commands.push(...lightShapes.drawLightSource(lx, ly, Math.floor(canvasSize * 0.05)));
|
|
23
|
+
|
|
24
|
+
// Draw shaded sphere
|
|
25
|
+
commands.push(...lightShapes.drawShadedSphere(cx, cy, r, lightAngle));
|
|
26
|
+
|
|
27
|
+
return commands;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = { lessonLightZones };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from material_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Transparent (Glass)
|
|
8
|
+
* Demonstrates Fresnel effect, sharp reflections, and light transmission.
|
|
9
|
+
*/
|
|
10
|
+
function lessonMaterialGlass(canvasSize = 32) {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx = Math.floor(canvasSize / 2);
|
|
13
|
+
const cy = Math.floor(canvasSize / 2);
|
|
14
|
+
const r = Math.floor(canvasSize * 0.35);
|
|
15
|
+
|
|
16
|
+
commands.push(...materialShapes.drawGlassSphere(cx, cy, r));
|
|
17
|
+
|
|
18
|
+
return commands;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { lessonMaterialGlass };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from material_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Shiny vs Matte (Metal vs Plastic/Rubber)
|
|
8
|
+
* Compares high contrast sharp highlights vs low contrast diffused highlights.
|
|
9
|
+
*/
|
|
10
|
+
function lessonMaterialShiny(canvasSize = 32) {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx1 = Math.floor(canvasSize * 0.3);
|
|
13
|
+
const cx2 = Math.floor(canvasSize * 0.7);
|
|
14
|
+
const cy = Math.floor(canvasSize / 2);
|
|
15
|
+
const r = Math.floor(canvasSize * 0.2);
|
|
16
|
+
|
|
17
|
+
// 1. Metal Sphere (Left)
|
|
18
|
+
commands.push(...materialShapes.drawMetalSphere(cx1, cy, r));
|
|
19
|
+
|
|
20
|
+
// 2. Matte/Plastic Sphere (Right)
|
|
21
|
+
commands.push(...materialShapes.drawMatteSphere(cx2, cy, r, '#e65100'));
|
|
22
|
+
|
|
23
|
+
return commands;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = { lessonMaterialShiny };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from material_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Texture (Wood vs Stone)
|
|
8
|
+
* Compares organic lines vs rough cracks.
|
|
9
|
+
*/
|
|
10
|
+
function lessonMaterialTexture(canvasSize = 32) {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx1 = Math.floor(canvasSize * 0.3);
|
|
13
|
+
const cx2 = Math.floor(canvasSize * 0.7);
|
|
14
|
+
const cy = Math.floor(canvasSize / 2);
|
|
15
|
+
const r = Math.floor(canvasSize * 0.2);
|
|
16
|
+
|
|
17
|
+
// 1. Wood Sphere (Left)
|
|
18
|
+
commands.push(...materialShapes.drawTexturedSphere(cx1, cy, r, 'wood'));
|
|
19
|
+
|
|
20
|
+
// 2. Stone Sphere (Right)
|
|
21
|
+
commands.push(...materialShapes.drawTexturedSphere(cx2, cy, r, 'stone'));
|
|
22
|
+
|
|
23
|
+
return commands;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = { lessonMaterialTexture };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from perspective_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: 1-Point Perspective
|
|
8
|
+
*/
|
|
9
|
+
function lesson1PointPerspective(canvasSize = 32, color = '#2196f3') {
|
|
10
|
+
const commands = [];
|
|
11
|
+
const horizonY = Math.floor(canvasSize * 0.4);
|
|
12
|
+
const vpX = Math.floor(canvasSize * 0.5);
|
|
13
|
+
const vpY = horizonY;
|
|
14
|
+
|
|
15
|
+
// Horizon & VP
|
|
16
|
+
commands.push(...perspShapes.drawHorizon(canvasSize, horizonY));
|
|
17
|
+
commands.push(...perspShapes.drawVP(vpX, vpY));
|
|
18
|
+
|
|
19
|
+
// Box below horizon (seeing top face)
|
|
20
|
+
const w = Math.floor(canvasSize * 0.2);
|
|
21
|
+
const h = Math.floor(canvasSize * 0.15);
|
|
22
|
+
commands.push(...perspShapes.draw1PointBox(vpX, vpY, Math.floor(canvasSize * 0.2), horizonY + Math.floor(canvasSize * 0.2), w, h, 0.4, color));
|
|
23
|
+
|
|
24
|
+
// Box above horizon (seeing bottom face)
|
|
25
|
+
commands.push(...perspShapes.draw1PointBox(vpX, vpY, Math.floor(canvasSize * 0.6), horizonY - Math.floor(canvasSize * 0.3), w, h, 0.4, '#e91e63'));
|
|
26
|
+
|
|
27
|
+
return commands;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = { lesson1PointPerspective };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from perspective_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: 2-Point Perspective
|
|
8
|
+
*/
|
|
9
|
+
function lesson2PointPerspective(canvasSize = 32, color = '#4caf50') {
|
|
10
|
+
const commands = [];
|
|
11
|
+
const horizonY = Math.floor(canvasSize * 0.5);
|
|
12
|
+
const vp1X = Math.floor(canvasSize * 0.1);
|
|
13
|
+
const vp2X = Math.floor(canvasSize * 0.9);
|
|
14
|
+
|
|
15
|
+
// Horizon & VPs
|
|
16
|
+
commands.push(...perspShapes.drawHorizon(canvasSize, horizonY));
|
|
17
|
+
commands.push(...perspShapes.drawVP(vp1X, horizonY));
|
|
18
|
+
commands.push(...perspShapes.drawVP(vp2X, horizonY));
|
|
19
|
+
|
|
20
|
+
// 2-Point Box straddling the horizon
|
|
21
|
+
const startX = Math.floor(canvasSize * 0.4);
|
|
22
|
+
const startY = Math.floor(canvasSize * 0.3);
|
|
23
|
+
const h = Math.floor(canvasSize * 0.4);
|
|
24
|
+
|
|
25
|
+
commands.push(...perspShapes.draw2PointBox(vp1X, horizonY, vp2X, horizonY, startX, startY, h, 0.3, 0.4, color));
|
|
26
|
+
|
|
27
|
+
return commands;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = { lesson2PointPerspective };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from perspective_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: 3-Point Perspective (Bird's eye view)
|
|
8
|
+
*/
|
|
9
|
+
function lesson3PointPerspective(canvasSize = 32, color = '#ff9800') {
|
|
10
|
+
const commands = [];
|
|
11
|
+
const horizonY = Math.floor(canvasSize * 0.2);
|
|
12
|
+
const vp1X = Math.floor(canvasSize * 0.1);
|
|
13
|
+
const vp2X = Math.floor(canvasSize * 0.9);
|
|
14
|
+
const vp3X = Math.floor(canvasSize * 0.5);
|
|
15
|
+
const vp3Y = Math.floor(canvasSize * 1.5); // VP3 far below (Bird's eye)
|
|
16
|
+
|
|
17
|
+
// Horizon & VPs
|
|
18
|
+
commands.push(...perspShapes.drawHorizon(canvasSize, horizonY));
|
|
19
|
+
commands.push(...perspShapes.drawVP(vp1X, horizonY));
|
|
20
|
+
commands.push(...perspShapes.drawVP(vp2X, horizonY));
|
|
21
|
+
// VP3 is usually off-canvas, but we draw a line to it to show direction
|
|
22
|
+
|
|
23
|
+
// We approximate a 3-point box by drawing converging vertical lines to VP3
|
|
24
|
+
const topY = Math.floor(canvasSize * 0.4);
|
|
25
|
+
const h = Math.floor(canvasSize * 0.4);
|
|
26
|
+
|
|
27
|
+
// Center edge converging to VP3
|
|
28
|
+
commands.push(shapes.drawLine(vp3X, topY, vp3X, topY+h, color)); // simplified
|
|
29
|
+
commands.push(shapes.drawLine(vp3X, topY+h, vp3X, vp3Y, '#e0e0e0')); // Guide to VP3
|
|
30
|
+
|
|
31
|
+
// Left and Right top edges to VP1, VP2
|
|
32
|
+
commands.push(shapes.drawLine(vp3X, topY, vp1X, horizonY, '#e0e0e0'));
|
|
33
|
+
commands.push(shapes.drawLine(vp3X, topY, vp2X, horizonY, '#e0e0e0'));
|
|
34
|
+
|
|
35
|
+
// Draw the rest of the box structure to simulate 3-point
|
|
36
|
+
const lX = vp3X - Math.floor(canvasSize * 0.15);
|
|
37
|
+
const rX = vp3X + Math.floor(canvasSize * 0.2);
|
|
38
|
+
// Vertical edges also converge to VP3 slightly (foreshortening)
|
|
39
|
+
commands.push(shapes.drawLine(lX, topY + Math.floor(canvasSize * 0.1), lX + 2, topY + h, color));
|
|
40
|
+
commands.push(shapes.drawLine(rX, topY + Math.floor(canvasSize * 0.15), rX - 3, topY + h - 5, color));
|
|
41
|
+
|
|
42
|
+
return commands;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { lesson3PointPerspective };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from perspective_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Foreshortening (Depth foreshortening)
|
|
8
|
+
* Drawing a cylinder pointing directly at the viewer
|
|
9
|
+
*/
|
|
10
|
+
function lessonForeshortening(canvasSize = 32, color = '#9c27b0') {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx = Math.floor(canvasSize / 2);
|
|
13
|
+
const cy = Math.floor(canvasSize / 2);
|
|
14
|
+
|
|
15
|
+
// Draw overlapping circles getting larger (coming towards viewer)
|
|
16
|
+
const numCircles = 5;
|
|
17
|
+
const maxR = Math.floor(canvasSize * 0.4);
|
|
18
|
+
const minR = Math.floor(canvasSize * 0.15);
|
|
19
|
+
|
|
20
|
+
for(let i=0; i<numCircles; i++) {
|
|
21
|
+
const t = i / (numCircles - 1); // 0 to 1
|
|
22
|
+
// Radius grows exponentially to simulate perspective
|
|
23
|
+
const r = minR + (maxR - minR) * (t * t);
|
|
24
|
+
// Y position shifts slightly to show overlap
|
|
25
|
+
const y = cy - Math.floor(canvasSize * 0.2) + Math.floor(canvasSize * 0.4 * t);
|
|
26
|
+
|
|
27
|
+
// Draw the circle
|
|
28
|
+
commands.push(shapes.drawCircle(cx, y, Math.floor(r), color, false));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Draw bounding lines converging
|
|
32
|
+
commands.push(shapes.drawLine(cx - minR, cy - Math.floor(canvasSize * 0.2), cx - maxR, cy + Math.floor(canvasSize * 0.2), '#bdbdbd'));
|
|
33
|
+
commands.push(shapes.drawLine(cx + minR, cy - Math.floor(canvasSize * 0.2), cx + maxR, cy + Math.floor(canvasSize * 0.2), '#bdbdbd'));
|
|
34
|
+
|
|
35
|
+
return commands;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = { lessonForeshortening };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from sky_lessons_1.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson 1: Sun Shapes (Hình dạng mặt trời)
|
|
8
|
+
* Compares Basic, Soft, and Rays
|
|
9
|
+
*/
|
|
10
|
+
function lessonSunShapes(canvasSize = 32) {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const y = Math.floor(canvasSize / 2);
|
|
13
|
+
const r = Math.floor(canvasSize * 0.15);
|
|
14
|
+
|
|
15
|
+
// Left: Basic
|
|
16
|
+
commands.push(...skyShapes1.drawSunBasic(Math.floor(canvasSize * 0.2), y, r));
|
|
17
|
+
// Center: Soft
|
|
18
|
+
commands.push(...skyShapes1.drawSunSoft(Math.floor(canvasSize * 0.5), y, r));
|
|
19
|
+
// Right: Rays
|
|
20
|
+
commands.push(...skyShapes1.drawSunRays(Math.floor(canvasSize * 0.8), y, r));
|
|
21
|
+
|
|
22
|
+
return commands;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = { lessonSunShapes };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from sky_lessons_1.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson 2: Sunset Colors (Màu sắc buổi chiều)
|
|
8
|
+
* Shows the progression of colors from blue to yellow
|
|
9
|
+
*/
|
|
10
|
+
function lessonSunsetColors(canvasSize = 32) {
|
|
11
|
+
const commands = [];
|
|
12
|
+
|
|
13
|
+
// The classic sunset gradient: Blue -> Purple -> Pink -> Orange -> Yellow (top to bottom)
|
|
14
|
+
const sunsetPalette = [
|
|
15
|
+
'#3f51b5', // Blue
|
|
16
|
+
'#9c27b0', // Purple
|
|
17
|
+
'#e91e63', // Pink
|
|
18
|
+
'#ff9800', // Orange
|
|
19
|
+
'#ffeb3b' // Yellow
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
commands.push(...skyShapes1.drawSkyGradient(0, 0, canvasSize, canvasSize, sunsetPalette));
|
|
23
|
+
|
|
24
|
+
return commands;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = { lessonSunsetColors };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from sky_lessons_1.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson 3: Sunset Sky (Bầu trời hoàng hôn)
|
|
8
|
+
* Combines the gradient sky with a soft sun setting at the bottom
|
|
9
|
+
*/
|
|
10
|
+
function lessonSunsetSky(canvasSize = 32) {
|
|
11
|
+
const commands = [];
|
|
12
|
+
|
|
13
|
+
// 1. Draw the Sky
|
|
14
|
+
const sunsetPalette = [
|
|
15
|
+
'#1a237e', // Dark Blue
|
|
16
|
+
'#512da8', // Deep Purple
|
|
17
|
+
'#c2185b', // Magenta
|
|
18
|
+
'#ff5722', // Deep Orange
|
|
19
|
+
'#ffb300' // Amber
|
|
20
|
+
];
|
|
21
|
+
commands.push(...skyShapes1.drawSkyGradient(0, 0, canvasSize, canvasSize, sunsetPalette));
|
|
22
|
+
|
|
23
|
+
// 2. Draw the Sun (Soft glowing sun near the bottom)
|
|
24
|
+
const cx = Math.floor(canvasSize / 2);
|
|
25
|
+
const cy = Math.floor(canvasSize * 0.8);
|
|
26
|
+
const r = Math.floor(canvasSize * 0.15);
|
|
27
|
+
commands.push(...skyShapes1.drawSunSoft(cx, cy, r));
|
|
28
|
+
|
|
29
|
+
return commands;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = { lessonSunsetSky };
|
|
@@ -1,44 +1,7 @@
|
|
|
1
|
-
const shapes = require('./shapes');
|
|
2
|
-
const structureShapes = require('./structure_shapes');
|
|
3
|
-
const shapes3d = require('./3d_shapes');
|
|
4
|
-
const ellipseShapes = require('./ellipse_shapes');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Lesson: XYZ Axes (Vertical, Horizontal, Depth)
|
|
8
|
-
*/
|
|
9
|
-
function lessonXYZAxes(canvasSize = 32, color = '#2196f3') {
|
|
10
|
-
const commands = [];
|
|
11
|
-
const cx = Math.floor(canvasSize / 2);
|
|
12
|
-
const cy = Math.floor(canvasSize / 2);
|
|
13
|
-
const length = Math.floor(canvasSize * 0.4);
|
|
14
|
-
|
|
15
|
-
// Draw the axes
|
|
16
|
-
commands.push(...structureShapes.drawXYZAxes(cx, cy, length));
|
|
17
|
-
|
|
18
|
-
// Draw a simple box aligned with these axes to show how objects follow them
|
|
19
|
-
const w = Math.floor(length * 0.5);
|
|
20
|
-
const h = Math.floor(length * 0.5);
|
|
21
|
-
const d = Math.floor(length * 0.5);
|
|
22
|
-
// Using a lighter color for the reference box
|
|
23
|
-
commands.push(...shapes3d.drawWireframeBox(cx + Math.floor(w/2), cy - Math.floor(h/2), w, h, d, '#e0e0e0'));
|
|
24
|
-
|
|
25
|
-
return commands;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
1
|
/**
|
|
29
|
-
*
|
|
2
|
+
* Auto-extracted from structure_lessons.js
|
|
30
3
|
*/
|
|
31
|
-
|
|
32
|
-
const commands = [];
|
|
33
|
-
const cx = Math.floor(canvasSize / 2);
|
|
34
|
-
const cy = Math.floor(canvasSize / 2);
|
|
35
|
-
const totalHeight = Math.floor(canvasSize * 0.8);
|
|
36
|
-
|
|
37
|
-
// Draw bottle structure showing cross-sections and central axis
|
|
38
|
-
commands.push(...structureShapes.drawBottleAnatomy(cx, cy, totalHeight, color));
|
|
39
|
-
|
|
40
|
-
return commands;
|
|
41
|
-
}
|
|
4
|
+
const shapes = require('../../shapes');
|
|
42
5
|
|
|
43
6
|
/**
|
|
44
7
|
* Lesson: Axis Orientation (Object pointing along different axes)
|
|
@@ -86,17 +49,4 @@ function lessonAxisOrientation(canvasSize = 32, color = '#00bcd4') {
|
|
|
86
49
|
return commands;
|
|
87
50
|
}
|
|
88
51
|
|
|
89
|
-
|
|
90
|
-
return [
|
|
91
|
-
{ id: 'structure_xyz', name: 'XYZ Axes', description: 'Understanding 3D space directions (Vertical, Horizontal, Depth)', fn: lessonXYZAxes },
|
|
92
|
-
{ id: 'structure_bottle', name: 'Complex Structure (Bottle)', description: 'Analyzing an object using a central axis and multiple cross-sections', fn: lessonComplexStructure },
|
|
93
|
-
{ id: 'structure_orientation', name: 'Axis Orientation', description: 'Identifying which axis an object is oriented along', fn: lessonAxisOrientation },
|
|
94
|
-
];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
module.exports = {
|
|
98
|
-
lessonXYZAxes,
|
|
99
|
-
lessonComplexStructure,
|
|
100
|
-
lessonAxisOrientation,
|
|
101
|
-
getStructureLessonCatalog
|
|
102
|
-
};
|
|
52
|
+
module.exports = { lessonAxisOrientation };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from structure_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Complex Structure Analysis (e.g. A Bottle)
|
|
8
|
+
*/
|
|
9
|
+
function lessonComplexStructure(canvasSize = 32, color = '#9c27b0') {
|
|
10
|
+
const commands = [];
|
|
11
|
+
const cx = Math.floor(canvasSize / 2);
|
|
12
|
+
const cy = Math.floor(canvasSize / 2);
|
|
13
|
+
const totalHeight = Math.floor(canvasSize * 0.8);
|
|
14
|
+
|
|
15
|
+
// Draw bottle structure showing cross-sections and central axis
|
|
16
|
+
commands.push(...structureShapes.drawBottleAnatomy(cx, cy, totalHeight, color));
|
|
17
|
+
|
|
18
|
+
return commands;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { lessonComplexStructure };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from structure_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: XYZ Axes (Vertical, Horizontal, Depth)
|
|
8
|
+
*/
|
|
9
|
+
function lessonXYZAxes(canvasSize = 32, color = '#2196f3') {
|
|
10
|
+
const commands = [];
|
|
11
|
+
const cx = Math.floor(canvasSize / 2);
|
|
12
|
+
const cy = Math.floor(canvasSize / 2);
|
|
13
|
+
const length = Math.floor(canvasSize * 0.4);
|
|
14
|
+
|
|
15
|
+
// Draw the axes
|
|
16
|
+
commands.push(...structureShapes.drawXYZAxes(cx, cy, length));
|
|
17
|
+
|
|
18
|
+
// Draw a simple box aligned with these axes to show how objects follow them
|
|
19
|
+
const w = Math.floor(length * 0.5);
|
|
20
|
+
const h = Math.floor(length * 0.5);
|
|
21
|
+
const d = Math.floor(length * 0.5);
|
|
22
|
+
// Using a lighter color for the reference box
|
|
23
|
+
commands.push(...shapes3d.drawWireframeBox(cx + Math.floor(w/2), cy - Math.floor(h/2), w, h, d, '#e0e0e0'));
|
|
24
|
+
|
|
25
|
+
return commands;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = { lessonXYZAxes };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from surface_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Chair Analysis (Analyzing surfaces and edges of a chair)
|
|
8
|
+
*/
|
|
9
|
+
function lessonChairAnalysis(canvasSize = 32, color = '#795548') {
|
|
10
|
+
const cx = Math.floor(canvasSize / 2);
|
|
11
|
+
const cy = Math.floor(canvasSize / 2);
|
|
12
|
+
const w = Math.floor(canvasSize * 0.3);
|
|
13
|
+
|
|
14
|
+
return surfaceShapes.drawChairAnalysis(cx, cy, w);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { lessonChairAnalysis };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from surface_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Cup Analysis (Analyzing surfaces of a cup)
|
|
8
|
+
*/
|
|
9
|
+
function lessonCupAnalysis(canvasSize = 32, color = '#607d8b') {
|
|
10
|
+
const cx = Math.floor(canvasSize / 2);
|
|
11
|
+
const cy = Math.floor(canvasSize / 2);
|
|
12
|
+
const r = Math.floor(canvasSize * 0.2);
|
|
13
|
+
const h = Math.floor(canvasSize * 0.4);
|
|
14
|
+
|
|
15
|
+
return surfaceShapes.drawCupAnalysis(cx, cy, r, h);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = { lessonCupAnalysis };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from surface_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Edge Types (Hard sharp corners vs Soft rounded edges)
|
|
8
|
+
*/
|
|
9
|
+
function lessonEdgeTypes(canvasSize = 32, color = '#ff5722') {
|
|
10
|
+
const commands = [];
|
|
11
|
+
const qX1 = Math.floor(canvasSize * 0.3);
|
|
12
|
+
const qX2 = Math.floor(canvasSize * 0.7);
|
|
13
|
+
const midY = Math.floor(canvasSize / 2);
|
|
14
|
+
const w = Math.floor(canvasSize * 0.25);
|
|
15
|
+
|
|
16
|
+
// 1. Hard Edge (Sharp corners)
|
|
17
|
+
commands.push(shapes.drawRectangle(qX1 - w/2, midY - w/2, w, w, '#e91e63', false));
|
|
18
|
+
|
|
19
|
+
// 2. Soft Edge / Transitional
|
|
20
|
+
// Draw a box with rounded corners (fillet)
|
|
21
|
+
const r = Math.floor(w * 0.2); // Corner radius
|
|
22
|
+
const rx = qX2 - w/2;
|
|
23
|
+
const ry = midY - w/2;
|
|
24
|
+
|
|
25
|
+
// Straight segments
|
|
26
|
+
commands.push(shapes.drawLine(rx + r, ry, rx + w - r, ry, '#00bcd4')); // Top
|
|
27
|
+
commands.push(shapes.drawLine(rx + w, ry + r, rx + w, ry + w - r, '#00bcd4')); // Right
|
|
28
|
+
commands.push(shapes.drawLine(rx + r, ry + w, rx + w - r, ry + w, '#00bcd4')); // Bottom
|
|
29
|
+
commands.push(shapes.drawLine(rx, ry + r, rx, ry + w - r, '#00bcd4')); // Left
|
|
30
|
+
|
|
31
|
+
// Rounded corners (approximated with small circles for visual simplicity)
|
|
32
|
+
commands.push(shapes.drawCircle(rx + r, ry + r, r, '#00bcd4', false)); // TL
|
|
33
|
+
commands.push(shapes.drawCircle(rx + w - r, ry + r, r, '#00bcd4', false)); // TR
|
|
34
|
+
commands.push(shapes.drawCircle(rx + w - r, ry + w - r, r, '#00bcd4', false)); // BR
|
|
35
|
+
commands.push(shapes.drawCircle(rx + r, ry + w - r, r, '#00bcd4', false)); // BL
|
|
36
|
+
|
|
37
|
+
return commands;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = { lessonEdgeTypes };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from surface_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Surface Types (Flat, convex, concave)
|
|
8
|
+
*/
|
|
9
|
+
function lessonSurfaceTypes(canvasSize = 32, color = '#2196f3') {
|
|
10
|
+
const commands = [];
|
|
11
|
+
const midY = Math.floor(canvasSize / 2);
|
|
12
|
+
const qX = Math.floor(canvasSize / 4);
|
|
13
|
+
const r = Math.floor(canvasSize * 0.15);
|
|
14
|
+
|
|
15
|
+
// 1. Flat Plane
|
|
16
|
+
const w = Math.floor(canvasSize * 0.2);
|
|
17
|
+
commands.push(shapes.drawRectangle(qX - w/2, midY - w/2, w, w, '#4caf50', false));
|
|
18
|
+
// Add some grid lines to show it's flat
|
|
19
|
+
commands.push(shapes.drawLine(qX, midY - w/2, qX, midY + w/2, '#4caf50'));
|
|
20
|
+
commands.push(shapes.drawLine(qX - w/2, midY, qX + w/2, midY, '#4caf50'));
|
|
21
|
+
|
|
22
|
+
// 2. Convex Surface (e.g. Dome/Sphere)
|
|
23
|
+
// We use an ellipse that curves outwards (downwards)
|
|
24
|
+
commands.push(shapes.drawEllipse(qX * 2, midY, r, r, '#ff9800', false));
|
|
25
|
+
// Cross contour curving DOWN (convex towards viewer)
|
|
26
|
+
commands.push(shapes.drawEllipse(qX * 2, midY + Math.floor(r*0.2), r, Math.floor(r*0.3), '#ff9800', false));
|
|
27
|
+
|
|
28
|
+
// 3. Concave Surface (e.g. Bowl)
|
|
29
|
+
// Draw the top rim of a bowl
|
|
30
|
+
commands.push(shapes.drawEllipse(qX * 3, midY, r, Math.floor(r*0.3), '#9c27b0', false));
|
|
31
|
+
// Draw the bottom curve (the inside of the bowl)
|
|
32
|
+
const bowlPoints = [];
|
|
33
|
+
for(let i=0; i<=18; i++) {
|
|
34
|
+
const a = (i/18) * Math.PI; // 0 to 180 degrees (bottom half)
|
|
35
|
+
bowlPoints.push({ x: Math.round(qX * 3 + r * Math.cos(a)), y: Math.round(midY + r * Math.sin(a)) });
|
|
36
|
+
}
|
|
37
|
+
commands.push(shapes.drawPolyline(bowlPoints, '#9c27b0'));
|
|
38
|
+
|
|
39
|
+
return commands;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = { lessonSurfaceTypes };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from transform_lessons_1.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Bend (Curved bending)
|
|
8
|
+
* Cylinder -> Bent Tube
|
|
9
|
+
*/
|
|
10
|
+
function lessonBend(canvasSize = 32, color = '#e91e63') {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx = Math.floor(canvasSize / 2);
|
|
13
|
+
const cy = Math.floor(canvasSize / 2);
|
|
14
|
+
const r = Math.floor(canvasSize * 0.1);
|
|
15
|
+
const length = Math.floor(canvasSize * 0.35);
|
|
16
|
+
|
|
17
|
+
// Original straight tube (ghost, pointing right)
|
|
18
|
+
commands.push(shapes.drawLine(cx, cy - r, cx + length * 2, cy - r, '#bdbdbd'));
|
|
19
|
+
commands.push(shapes.drawLine(cx, cy + r, cx + length * 2, cy + r, '#bdbdbd'));
|
|
20
|
+
|
|
21
|
+
// Bent tube
|
|
22
|
+
commands.push(...transformShapes.drawBentTube(cx, cy + length, r, length, color));
|
|
23
|
+
|
|
24
|
+
return commands;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = { lessonBend };
|