@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.
Files changed (132) hide show
  1. package/clear-firebase.js +37 -0
  2. package/domains/art-tree/README.md +134 -0
  3. package/domains/art-tree/REORGANIZATION_PLAN.md +168 -0
  4. package/domains/art-tree/REORGANIZATION_SUMMARY.md +260 -0
  5. package/domains/art-tree/index.js +58 -58
  6. package/domains/art-tree/lessons/3d/box-properties.js +38 -0
  7. package/domains/art-tree/lessons/3d/cone-properties.js +31 -0
  8. package/domains/art-tree/lessons/3d/cylinder-properties.js +29 -0
  9. package/domains/art-tree/lessons/3d/sphere-properties.js +25 -0
  10. package/domains/art-tree/lessons/advanced/angles.js +30 -0
  11. package/domains/art-tree/lessons/advanced/distances.js +26 -0
  12. package/domains/art-tree/lessons/advanced/shape-ratios.js +25 -0
  13. package/domains/art-tree/lessons/advanced/shape-relationships.js +28 -0
  14. package/domains/art-tree/lessons/advanced/symmetry-and-axis.js +26 -0
  15. package/domains/art-tree/{analysis_lessons.js → lessons/analysis/object-analysis.js} +5 -16
  16. package/domains/art-tree/lessons/basic/circles.js +26 -0
  17. package/domains/art-tree/lessons/basic/composition.js +34 -0
  18. package/domains/art-tree/lessons/basic/curves.js +31 -0
  19. package/domains/art-tree/lessons/basic/ellipses.js +26 -0
  20. package/domains/art-tree/lessons/basic/freehand.js +19 -0
  21. package/domains/art-tree/lessons/basic/index.js +36 -0
  22. package/domains/art-tree/lessons/basic/lines.js +38 -0
  23. package/domains/art-tree/lessons/basic/parallel-and-intersecting.js +22 -0
  24. package/domains/art-tree/lessons/basic/polygons.js +25 -0
  25. package/domains/art-tree/lessons/basic/proportions-and-angles.js +20 -0
  26. package/domains/art-tree/lessons/basic/spiral.js +21 -0
  27. package/domains/art-tree/lessons/basic/squares.js +28 -0
  28. package/domains/art-tree/lessons/basic/strokes.js +23 -0
  29. package/domains/art-tree/lessons/basic/triangles.js +30 -0
  30. package/domains/art-tree/lessons/cross-sections/bottle-sections.js +26 -0
  31. package/domains/art-tree/lessons/cross-sections/glass-sections.js +24 -0
  32. package/domains/art-tree/lessons/cross-sections/head-sections.js +17 -0
  33. package/domains/art-tree/lessons/curves/curve-properties.js +50 -0
  34. package/domains/art-tree/lessons/curves/curve-topology.js +45 -0
  35. package/domains/art-tree/lessons/curves/curve-types.js +44 -0
  36. package/domains/art-tree/lessons/ellipses/coaxial-ellipses.js +29 -0
  37. package/domains/art-tree/lessons/ellipses/ellipse-anatomy.js +26 -0
  38. package/domains/art-tree/lessons/ellipses/ellipse-orientations.js +28 -0
  39. package/domains/art-tree/lessons/ellipses/ellipse-proportions.js +27 -0
  40. package/domains/art-tree/lessons/hidden/hidden-box.js +20 -0
  41. package/domains/art-tree/lessons/hidden/hidden-cup.js +19 -0
  42. package/domains/art-tree/lessons/hidden/hidden-head.js +18 -0
  43. package/domains/art-tree/lessons/index.js +42 -0
  44. package/domains/art-tree/{layer_lessons.js → lessons/layers/layer-step.js} +5 -16
  45. package/domains/art-tree/lessons/lighting/contact-shadow.js +33 -0
  46. package/domains/art-tree/lessons/lighting/light-direction.js +30 -0
  47. package/domains/art-tree/lessons/lighting/light-zones.js +30 -0
  48. package/domains/art-tree/lessons/materials/material-glass.js +21 -0
  49. package/domains/art-tree/lessons/materials/material-shiny.js +26 -0
  50. package/domains/art-tree/lessons/materials/material-texture.js +26 -0
  51. package/domains/art-tree/lessons/perspective/1point-perspective.js +30 -0
  52. package/domains/art-tree/lessons/perspective/2point-perspective.js +30 -0
  53. package/domains/art-tree/lessons/perspective/3point-perspective.js +45 -0
  54. package/domains/art-tree/lessons/perspective/foreshortening.js +38 -0
  55. package/domains/art-tree/lessons/sky/sun-shapes.js +25 -0
  56. package/domains/art-tree/lessons/sky/sunset-colors.js +27 -0
  57. package/domains/art-tree/lessons/sky/sunset-sky.js +32 -0
  58. package/domains/art-tree/{structure_lessons.js → lessons/structure/axis-orientation.js} +3 -53
  59. package/domains/art-tree/lessons/structure/complex-structure.js +21 -0
  60. package/domains/art-tree/lessons/structure/x-yzaxes.js +28 -0
  61. package/domains/art-tree/lessons/surfaces/chair-analysis.js +17 -0
  62. package/domains/art-tree/lessons/surfaces/cup-analysis.js +18 -0
  63. package/domains/art-tree/lessons/surfaces/edge-types.js +40 -0
  64. package/domains/art-tree/lessons/surfaces/surface-types.js +42 -0
  65. package/domains/art-tree/lessons/transforms/bend.js +27 -0
  66. package/domains/art-tree/{transform_lessons_2.js → lessons/transforms/combine.js} +3 -54
  67. package/domains/art-tree/lessons/transforms/cut.js +25 -0
  68. package/domains/art-tree/lessons/transforms/hollow.js +24 -0
  69. package/domains/art-tree/lessons/transforms/rotate.js +16 -0
  70. package/domains/art-tree/lessons/transforms/squash.js +31 -0
  71. package/domains/art-tree/lessons/transforms/stretch.js +31 -0
  72. package/domains/art-tree/lessons/transforms/taper-swell.js +33 -0
  73. package/domains/art-tree/{vocab_lessons.js → lessons/vocab/vocab-house.js} +5 -16
  74. package/domains/art-tree/lib/tool-register.js +104 -0
  75. package/domains/art-tree/lib/validators.js +78 -0
  76. package/domains/art-tree/shapes/grid.js +37 -0
  77. package/domains/art-tree/shapes/polyline.js +26 -0
  78. package/domains/art-tree/{3d_tools.js → tools/3d.js} +2 -2
  79. package/domains/art-tree/{advanced_tools.js → tools/advanced.js} +2 -2
  80. package/domains/art-tree/{analysis_tools.js → tools/analysis.js} +2 -2
  81. package/domains/art-tree/{tools.js → tools/basic.js} +3 -3
  82. package/domains/art-tree/{cross_section_tools.js → tools/cross-sections.js} +2 -2
  83. package/domains/art-tree/{curve_tools.js → tools/curves.js} +2 -2
  84. package/domains/art-tree/{ellipse_tools.js → tools/ellipses.js} +2 -2
  85. package/domains/art-tree/{hidden_tools.js → tools/hidden.js} +2 -2
  86. package/domains/art-tree/tools/index.js +53 -0
  87. package/domains/art-tree/{layer_tools.js → tools/layers.js} +2 -2
  88. package/domains/art-tree/{light_tools.js → tools/lighting.js} +2 -2
  89. package/domains/art-tree/{material_tools.js → tools/materials.js} +2 -2
  90. package/domains/art-tree/{perspective_tools.js → tools/perspective.js} +2 -2
  91. package/domains/art-tree/{sky_tools.js → tools/sky.js} +2 -2
  92. package/domains/art-tree/{structure_tools.js → tools/structure.js} +2 -2
  93. package/domains/art-tree/{surface_tools.js → tools/surfaces.js} +2 -2
  94. package/domains/art-tree/{transform_tools.js → tools/transforms.js} +3 -3
  95. package/domains/art-tree/{vocab_tools.js → tools/vocab.js} +2 -2
  96. package/package.json +1 -1
  97. package/rules/prerequisites.js +30 -30
  98. package/rules/rules.js +1 -1
  99. package/rules/workflow.js +28 -20
  100. package/tools/canvas-tools.js +2 -2
  101. package/tools/drawing-tools.js +23 -12
  102. package/tools/workspace-tools.js +5 -4
  103. package/domains/art-tree/3d_lessons.js +0 -114
  104. package/domains/art-tree/advanced_lessons.js +0 -124
  105. package/domains/art-tree/cross_section_lessons.js +0 -65
  106. package/domains/art-tree/curve_lessons.js +0 -138
  107. package/domains/art-tree/ellipse_lessons.js +0 -105
  108. package/domains/art-tree/hidden_lessons.js +0 -55
  109. package/domains/art-tree/lessons.js +0 -305
  110. package/domains/art-tree/light_lessons.js +0 -92
  111. package/domains/art-tree/material_lessons.js +0 -71
  112. package/domains/art-tree/perspective_lessons.js +0 -138
  113. package/domains/art-tree/sky_lessons_1.js +0 -82
  114. package/domains/art-tree/surface_lessons.js +0 -112
  115. package/domains/art-tree/transform_lessons_1.js +0 -108
  116. /package/domains/art-tree/{3d_shapes.js → shapes/3d.js} +0 -0
  117. /package/domains/art-tree/{advanced_shapes.js → shapes/advanced.js} +0 -0
  118. /package/domains/art-tree/{analysis_shapes.js → shapes/analysis.js} +0 -0
  119. /package/domains/art-tree/{shapes.js → shapes/basic.js} +0 -0
  120. /package/domains/art-tree/{cross_section_shapes.js → shapes/cross-sections.js} +0 -0
  121. /package/domains/art-tree/{curve_shapes.js → shapes/curves.js} +0 -0
  122. /package/domains/art-tree/{ellipse_shapes.js → shapes/ellipses.js} +0 -0
  123. /package/domains/art-tree/{hidden_shapes.js → shapes/hidden.js} +0 -0
  124. /package/domains/art-tree/{layer_shapes.js → shapes/layers.js} +0 -0
  125. /package/domains/art-tree/{light_shapes.js → shapes/lighting.js} +0 -0
  126. /package/domains/art-tree/{material_shapes.js → shapes/materials.js} +0 -0
  127. /package/domains/art-tree/{perspective_shapes.js → shapes/perspective.js} +0 -0
  128. /package/domains/art-tree/{sky_shapes_1.js → shapes/sky.js} +0 -0
  129. /package/domains/art-tree/{structure_shapes.js → shapes/structure.js} +0 -0
  130. /package/domains/art-tree/{surface_shapes.js → shapes/surfaces.js} +0 -0
  131. /package/domains/art-tree/{transform_shapes.js → shapes/transforms.js} +0 -0
  132. /package/domains/art-tree/{vocab_shapes.js → shapes/vocab.js} +0 -0
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Auto-extracted from lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 6: Polygons — Multi-sided shapes.
8
+ * @param {number} canvasSize - Canvas dimension
9
+ * @param {string} color - Primary color
10
+ * @returns {Array<Object>} Array of command payloads
11
+ */
12
+ function lessonPolygons(canvasSize = 32, color = '#607d8b') {
13
+ const mid = Math.floor(canvasSize / 2);
14
+ const r = Math.floor(canvasSize * 0.35);
15
+ return [
16
+ // Pentagon
17
+ shapes.drawRegularPolygon(mid, mid, 5, r, '#4caf50', false),
18
+ // Hexagon (filled)
19
+ shapes.drawRegularPolygon(mid, mid, 6, Math.floor(r * 0.7), '#ff9800', true),
20
+ // Octagon
21
+ shapes.drawRegularPolygon(mid, mid, 8, Math.floor(r * 0.5), '#9c27b0', false),
22
+ ];
23
+ }
24
+
25
+ module.exports = { lessonPolygons };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Auto-extracted from lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 9: Proportions and Angles — Practice maintaining proportions and angles.
8
+ */
9
+ function lessonProportionsAndAngles(canvasSize = 32, color = '#3f51b5') {
10
+ const mid = Math.floor(canvasSize / 2);
11
+ const size1 = Math.floor(canvasSize * 0.4);
12
+ const size2 = Math.floor(size1 / 2);
13
+ return [
14
+ shapes.drawSquare(mid - Math.floor(size1/2), mid - Math.floor(size1/2), size1, color, false),
15
+ shapes.drawSquare(mid - Math.floor(size2/2), mid - Math.floor(size2/2), size2, '#e91e63', false),
16
+ shapes.drawLine(mid, mid, mid + size1, mid - size1, '#009688')
17
+ ];
18
+ }
19
+
20
+ module.exports = { lessonProportionsAndAngles };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Auto-extracted from lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 11: Spiral — Drawing spiral curves.
8
+ */
9
+ function lessonSpiral(canvasSize = 32, color = '#ff9800') {
10
+ const mid = Math.floor(canvasSize / 2);
11
+ const points = [];
12
+ const maxRadius = Math.floor(canvasSize * 0.4);
13
+ const loops = 3;
14
+ for (let angle = 0; angle < Math.PI * 2 * loops; angle += 0.3) {
15
+ const r = (angle / (Math.PI * 2 * loops)) * maxRadius;
16
+ points.push({ x: Math.round(mid + r * Math.cos(angle)), y: Math.round(mid + r * Math.sin(angle)) });
17
+ }
18
+ return shapes.drawPolyline(points, color);
19
+ }
20
+
21
+ module.exports = { lessonSpiral };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Auto-extracted from lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 2: Squares & Rectangles — Understanding right angles and proportions.
8
+ * @param {number} canvasSize - Canvas dimension
9
+ * @param {string} color - Primary color
10
+ * @returns {Array<Object>} Array of command payloads
11
+ */
12
+ function lessonSquares(canvasSize = 32, color = '#1565c0') {
13
+ const margin = Math.floor(canvasSize * 0.1);
14
+ const small = Math.floor(canvasSize * 0.2);
15
+ const large = Math.floor(canvasSize * 0.35);
16
+ return [
17
+ // Small square (outline)
18
+ shapes.drawSquare(margin, margin, small, color, false),
19
+ // Large square (filled)
20
+ shapes.drawSquare(canvasSize - margin - large, margin, large, '#ff7043', true),
21
+ // Rectangle (horizontal)
22
+ shapes.drawRectangle(margin, canvasSize - margin - small, large + small, small, '#4caf50', false),
23
+ // Rectangle (vertical, filled)
24
+ shapes.drawRectangle(canvasSize - margin - small, canvasSize - margin - large, small, large, '#9c27b0', true),
25
+ ];
26
+ }
27
+
28
+ module.exports = { lessonSquares };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Auto-extracted from lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 12: Strokes — Long strokes, short strokes, thick and thin lines.
8
+ */
9
+ function lessonStrokes(canvasSize = 32, color = '#2196f3') {
10
+ const margin = Math.floor(canvasSize * 0.1);
11
+ const y1 = Math.floor(canvasSize * 0.3);
12
+ const y2 = Math.floor(canvasSize * 0.5);
13
+ const y3 = Math.floor(canvasSize * 0.7);
14
+ return [
15
+ shapes.drawLine(margin, y1, canvasSize - margin, y1, color),
16
+ shapes.drawLine(margin, y2, Math.floor(canvasSize / 2), y2, '#4caf50'),
17
+ shapes.drawLine(margin, y3, canvasSize - margin, y3, '#f44336'),
18
+ shapes.drawLine(margin, y3 + 1, canvasSize - margin, y3 + 1, '#f44336'),
19
+ shapes.drawLine(margin, y3 + 2, canvasSize - margin, y3 + 2, '#f44336'),
20
+ ];
21
+ }
22
+
23
+ module.exports = { lessonStrokes };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Auto-extracted from lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 5: Triangles — Three-point shapes and stability.
8
+ * @param {number} canvasSize - Canvas dimension
9
+ * @param {string} color - Primary color
10
+ * @returns {Array<Object>} Array of command payloads
11
+ */
12
+ function lessonTriangles(canvasSize = 32, color = '#ff5722') {
13
+ const mid = Math.floor(canvasSize / 2);
14
+ const size = Math.floor(canvasSize * 0.4);
15
+ const margin = Math.floor(canvasSize * 0.1);
16
+ return [
17
+ // Equilateral triangle (outline)
18
+ shapes.drawEquilateralTriangle(mid, mid, size, color, false),
19
+ // Right triangle (filled)
20
+ shapes.drawTriangle([
21
+ { x: margin, y: canvasSize - margin },
22
+ { x: margin, y: margin },
23
+ { x: Math.floor(canvasSize * 0.35), y: canvasSize - margin },
24
+ ], '#3f51b5', true),
25
+ // Inverted triangle
26
+ shapes.drawEquilateralTriangle(mid, mid, Math.floor(size * 0.6), '#009688', true),
27
+ ];
28
+ }
29
+
30
+ module.exports = { lessonTriangles };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Auto-extracted from cross_section_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Bottle Sections (Base, Body, Shoulder, Neck, Mouth)
8
+ */
9
+ function lessonBottleSections(canvasSize = 32, color = '#2196f3') {
10
+ const cx = Math.floor(canvasSize / 2);
11
+ const totalH = Math.floor(canvasSize * 0.8);
12
+ const topY = Math.floor(canvasSize * 0.1);
13
+ const bottomY = topY + totalH;
14
+
15
+ const sections = [
16
+ { y: topY, r: Math.floor(canvasSize * 0.08) }, // Mouth (slightly open)
17
+ { y: topY + Math.floor(totalH * 0.1), r: Math.floor(canvasSize * 0.06) }, // Neck (narrow)
18
+ { y: topY + Math.floor(totalH * 0.3), r: Math.floor(canvasSize * 0.2) }, // Shoulder (shrinking to body)
19
+ { y: topY + Math.floor(totalH * 0.6), r: Math.floor(canvasSize * 0.25) }, // Body (wide)
20
+ { y: bottomY, r: Math.floor(canvasSize * 0.25) } // Base (wide)
21
+ ];
22
+
23
+ return csShapes.drawLoftedForm(cx, topY, bottomY, sections, color, true);
24
+ }
25
+
26
+ module.exports = { lessonBottleSections };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Auto-extracted from cross_section_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Glass Sections (Base, Mid, Mouth)
8
+ */
9
+ function lessonGlassSections(canvasSize = 32, color = '#9c27b0') {
10
+ const cx = Math.floor(canvasSize / 2);
11
+ const totalH = Math.floor(canvasSize * 0.6);
12
+ const topY = Math.floor(canvasSize * 0.2);
13
+ const bottomY = topY + totalH;
14
+
15
+ const sections = [
16
+ { y: topY, r: Math.floor(canvasSize * 0.3) }, // Mouth (wide)
17
+ { y: topY + Math.floor(totalH * 0.5), r: Math.floor(canvasSize * 0.2) }, // Mid body (widening)
18
+ { y: bottomY, r: Math.floor(canvasSize * 0.15) } // Base (small)
19
+ ];
20
+
21
+ return csShapes.drawLoftedForm(cx, topY, bottomY, sections, color, true);
22
+ }
23
+
24
+ module.exports = { lessonGlassSections };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Auto-extracted from cross_section_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Head Sections (Cranium, Face, Jaw)
8
+ */
9
+ function lessonHeadSections(canvasSize = 32, color = '#ff9800') {
10
+ const cx = Math.floor(canvasSize / 2);
11
+ const cy = Math.floor(canvasSize / 2);
12
+ const height = Math.floor(canvasSize * 0.8);
13
+
14
+ return csShapes.drawHeadStructure(cx, cy, height, color);
15
+ }
16
+
17
+ module.exports = { lessonHeadSections };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Auto-extracted from curve_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 3: Curve Properties (Start, Direction, Curvature, Inflection, Transition)
8
+ */
9
+ function lessonCurveProperties(canvasSize = 32, color = '#607d8b') {
10
+ const margin = Math.floor(canvasSize * 0.1);
11
+ const commands = [];
12
+
13
+ // 1. Start point and Direction (Top Left Curve)
14
+ const p0 = { x: margin, y: margin * 2 };
15
+ const p1 = { x: margin + canvasSize*0.3, y: margin };
16
+ const p2 = { x: margin + canvasSize*0.3, y: margin + canvasSize*0.3 };
17
+ commands.push(...curveShapes.drawQuadraticCurve(p0, p1, p2, color));
18
+ commands.push(curveShapes.drawStartMarker(p0.x, p0.y, '#00ff00')); // Green dot at start
19
+ commands.push(...curveShapes.drawDirectionArrow(p0, p1, p2, null, '#ff0000')); // Red arrow
20
+
21
+ // 2. Curvature comparison (Bottom Left)
22
+ // Strong vs Weak curve with same endpoints
23
+ const bp0 = { x: margin, y: canvasSize - margin };
24
+ const bp2 = { x: margin + canvasSize*0.4, y: canvasSize - margin };
25
+ // Weak curve
26
+ commands.push(...curveShapes.drawQuadraticCurve(bp0, { x: margin + canvasSize*0.2, y: canvasSize - margin - canvasSize*0.1 }, bp2, '#8bc34a'));
27
+ // Strong curve
28
+ commands.push(...curveShapes.drawQuadraticCurve(bp0, { x: margin + canvasSize*0.2, y: canvasSize - margin - canvasSize*0.4 }, bp2, '#388e3c'));
29
+
30
+ // 3. Inflection point (Top Right S Curve)
31
+ const sP0 = { x: canvasSize - margin - canvasSize*0.3, y: margin };
32
+ const sP1 = { x: canvasSize - margin, y: margin };
33
+ const sP2 = { x: canvasSize - margin - canvasSize*0.4, y: margin + canvasSize*0.3 };
34
+ const sP3 = { x: canvasSize - margin, y: margin + canvasSize*0.3 };
35
+ commands.push(...curveShapes.drawCubicCurve(sP0, sP1, sP2, sP3, '#03a9f4'));
36
+ // Inflection point roughly at t=0.5
37
+ const inflection = curveShapes.cubicBezier(sP0, sP1, sP2, sP3, 0.5);
38
+ commands.push(curveShapes.drawInflectionMarker(inflection.x, inflection.y, '#ff9800'));
39
+
40
+ // 4. Transition (Bottom Right - line transitioning to curve)
41
+ const startLine = { x: canvasSize - margin - canvasSize*0.3, y: canvasSize - margin - canvasSize*0.2 };
42
+ const transPt = { x: canvasSize - margin - canvasSize*0.1, y: canvasSize - margin - canvasSize*0.2 };
43
+ commands.push(shapes.drawLine(startLine.x, startLine.y, transPt.x, transPt.y, '#9e9e9e'));
44
+ // Curve starting tangentially
45
+ commands.push(...curveShapes.drawQuadraticCurve(transPt, { x: canvasSize - margin, y: canvasSize - margin - canvasSize*0.2 }, { x: canvasSize - margin, y: canvasSize - margin }, '#795548'));
46
+
47
+ return commands;
48
+ }
49
+
50
+ module.exports = { lessonCurveProperties };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Auto-extracted from curve_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 2: Curve Topology (Closed, Open, Symmetrical, Asymmetrical)
8
+ */
9
+ function lessonCurveTopology(canvasSize = 32, color = '#9c27b0') {
10
+ const mid = Math.floor(canvasSize / 2);
11
+ const q = Math.floor(canvasSize / 4);
12
+ const commands = [];
13
+
14
+ // Closed Curve (Circle-like using Bezier for demonstration)
15
+ // Since we already have drawCircle, we just draw a circle to represent a closed curve
16
+ commands.push(shapes.drawCircle(q, q, Math.floor(q*0.8), color, false));
17
+
18
+ // Open Curve (Quadratic)
19
+ commands.push(...curveShapes.drawQuadraticCurve(
20
+ { x: canvasSize - q*1.5, y: q },
21
+ { x: canvasSize - q*0.5, y: q - q/2 },
22
+ { x: canvasSize - q*0.5, y: q + q/2 },
23
+ '#3f51b5'
24
+ ));
25
+
26
+ // Symmetrical Curve (Parabola-like)
27
+ commands.push(...curveShapes.drawQuadraticCurve(
28
+ { x: q*0.5, y: canvasSize - q*0.5 },
29
+ { x: q, y: canvasSize - q*1.5 },
30
+ { x: q*1.5, y: canvasSize - q*0.5 },
31
+ '#00bcd4'
32
+ ));
33
+
34
+ // Asymmetrical Curve
35
+ commands.push(...curveShapes.drawQuadraticCurve(
36
+ { x: canvasSize - q*1.5, y: canvasSize - q*0.5 },
37
+ { x: canvasSize - q*0.2, y: canvasSize - q*1.8 }, // Pull point is skewed
38
+ { x: canvasSize - q*0.5, y: canvasSize - q*0.5 },
39
+ '#ff5722'
40
+ ));
41
+
42
+ return commands;
43
+ }
44
+
45
+ module.exports = { lessonCurveTopology };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Auto-extracted from curve_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 1: Curve Types (C, S, Convex, Concave)
8
+ */
9
+ function lessonCurveTypes(canvasSize = 32, color = '#2196f3') {
10
+ const margin = Math.floor(canvasSize * 0.1);
11
+ const commands = [];
12
+
13
+ const w = Math.floor(canvasSize / 2) - margin * 2;
14
+ const h = Math.floor(canvasSize / 2) - margin * 2;
15
+
16
+ // C Curve (Top Left)
17
+ const cP0 = { x: margin + w, y: margin };
18
+ const cP1 = { x: margin - w, y: margin + Math.floor(h/2) }; // Pulls curve left
19
+ const cP2 = { x: margin + w, y: margin + h };
20
+ commands.push(...curveShapes.drawQuadraticCurve(cP0, cP1, cP2, color));
21
+
22
+ // S Curve (Top Right)
23
+ const sP0 = { x: canvasSize - margin, y: margin };
24
+ const sP1 = { x: canvasSize - margin - w*2, y: margin };
25
+ const sP2 = { x: canvasSize - margin + w, y: margin + h };
26
+ const sP3 = { x: canvasSize - margin - w, y: margin + h };
27
+ commands.push(...curveShapes.drawCubicCurve(sP0, sP1, sP2, sP3, '#e91e63'));
28
+
29
+ // Convex (Bottom Left, viewed from bottom)
30
+ const cvxP0 = { x: margin, y: canvasSize - margin };
31
+ const cvxP1 = { x: margin + Math.floor(w/2), y: canvasSize - margin - h };
32
+ const cvxP2 = { x: margin + w, y: canvasSize - margin };
33
+ commands.push(...curveShapes.drawQuadraticCurve(cvxP0, cvxP1, cvxP2, '#4caf50'));
34
+
35
+ // Concave (Bottom Right, viewed from bottom)
36
+ const cnvP0 = { x: canvasSize - margin - w, y: canvasSize - margin - Math.floor(h/2) };
37
+ const cnvP1 = { x: canvasSize - margin - Math.floor(w/2), y: canvasSize - margin + h };
38
+ const cnvP2 = { x: canvasSize - margin, y: canvasSize - margin - Math.floor(h/2) };
39
+ commands.push(...curveShapes.drawQuadraticCurve(cnvP0, cnvP1, cnvP2, '#ff9800'));
40
+
41
+ return commands;
42
+ }
43
+
44
+ module.exports = { lessonCurveTypes };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Auto-extracted from ellipse_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Coaxial Ellipses (Multiple ellipses on the same axis)
8
+ */
9
+ function lessonCoaxialEllipses(canvasSize = 32, color = '#795548') {
10
+ const commands = [];
11
+ const cx = Math.floor(canvasSize / 2);
12
+ const rx = Math.floor(canvasSize * 0.3);
13
+
14
+ // Central axis line
15
+ commands.push(shapes.drawLine(cx, Math.floor(canvasSize * 0.1), cx, canvasSize - Math.floor(canvasSize * 0.1), '#bdbdbd'));
16
+
17
+ // Top ellipse (narrower, viewed from steeper angle)
18
+ commands.push(shapes.drawEllipse(cx, Math.floor(canvasSize * 0.2), rx, Math.floor(rx * 0.2), color, false));
19
+
20
+ // Middle ellipse
21
+ commands.push(shapes.drawEllipse(cx, Math.floor(canvasSize * 0.5), rx, Math.floor(rx * 0.3), color, false));
22
+
23
+ // Bottom ellipse (wider, viewed from less steep angle)
24
+ commands.push(shapes.drawEllipse(cx, canvasSize - Math.floor(canvasSize * 0.2), rx, Math.floor(rx * 0.4), color, false));
25
+
26
+ return commands;
27
+ }
28
+
29
+ module.exports = { lessonCoaxialEllipses };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Auto-extracted from ellipse_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Ellipse Anatomy (Symmetry, Major/Minor axes, Center)
8
+ */
9
+ function lessonEllipseAnatomy(canvasSize = 32, color = '#00bcd4') {
10
+ const commands = [];
11
+ const cx = Math.floor(canvasSize / 2);
12
+ const cy = Math.floor(canvasSize / 2);
13
+ const rx = Math.floor(canvasSize * 0.35);
14
+ const ry = Math.floor(canvasSize * 0.2);
15
+ const angle = Math.PI / 6; // 30 degrees tilt to show axes clearly
16
+
17
+ // Draw ellipse
18
+ commands.push(...ellipseShapes.drawRotatedEllipse(cx, cy, rx, ry, angle, color));
19
+
20
+ // Draw anatomy (axes and center)
21
+ commands.push(...ellipseShapes.drawEllipseAxes(cx, cy, rx, ry, angle));
22
+
23
+ return commands;
24
+ }
25
+
26
+ module.exports = { lessonEllipseAnatomy };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Auto-extracted from ellipse_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Ellipse Orientations (Horizontal, Vertical, Tilted)
8
+ */
9
+ function lessonEllipseOrientations(canvasSize = 32, color = '#2196f3') {
10
+ const commands = [];
11
+ const midY = Math.floor(canvasSize / 2);
12
+ const qX = Math.floor(canvasSize / 4);
13
+ const rLong = Math.floor(canvasSize * 0.2);
14
+ const rShort = Math.floor(canvasSize * 0.1);
15
+
16
+ // Horizontal (Left)
17
+ commands.push(shapes.drawEllipse(qX, midY, rLong, rShort, color, false));
18
+
19
+ // Vertical (Middle)
20
+ commands.push(shapes.drawEllipse(qX * 2, midY, rShort, rLong, '#e91e63', false));
21
+
22
+ // Tilted (Right) - 45 degrees
23
+ commands.push(...ellipseShapes.drawRotatedEllipse(qX * 3, midY, rLong, rShort, Math.PI / 4, '#4caf50'));
24
+
25
+ return commands;
26
+ }
27
+
28
+ module.exports = { lessonEllipseOrientations };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Auto-extracted from ellipse_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Ellipse Proportions (Wide vs Narrow)
8
+ */
9
+ function lessonEllipseProportions(canvasSize = 32, color = '#ff9800') {
10
+ const commands = [];
11
+ const midY = Math.floor(canvasSize / 2);
12
+ const qX = Math.floor(canvasSize / 4);
13
+ const rx = Math.floor(canvasSize * 0.2);
14
+
15
+ // Wide Ellipse (Closer to a circle)
16
+ commands.push(shapes.drawEllipse(qX, midY, rx, Math.floor(rx * 0.8), color, false));
17
+
18
+ // Medium Ellipse
19
+ commands.push(shapes.drawEllipse(qX * 2, midY, rx, Math.floor(rx * 0.4), '#9c27b0', false));
20
+
21
+ // Narrow Ellipse (Almost a line)
22
+ commands.push(shapes.drawEllipse(qX * 3, midY, rx, Math.floor(rx * 0.1), '#f44336', false));
23
+
24
+ return commands;
25
+ }
26
+
27
+ module.exports = { lessonEllipseProportions };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Auto-extracted from hidden_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Hidden Box (6-sided box)
8
+ * You see 3 faces, but you must understand all 6.
9
+ */
10
+ function lessonHiddenBox(canvasSize = 32, visibleColor = '#2196f3', hiddenColor = '#e0e0e0') {
11
+ const cx = Math.floor(canvasSize / 2);
12
+ const cy = Math.floor(canvasSize / 2);
13
+ const w = Math.floor(canvasSize * 0.4);
14
+ const h = Math.floor(canvasSize * 0.4);
15
+ const d = Math.floor(canvasSize * 0.4);
16
+
17
+ return hiddenShapes.drawXRayBox(cx, cy, w, h, d, visibleColor, hiddenColor);
18
+ }
19
+
20
+ module.exports = { lessonHiddenBox };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Auto-extracted from hidden_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Hidden Cup (Cup and inner bottom)
8
+ * You don't see the full inside bottom, but must understand how the wall goes down.
9
+ */
10
+ function lessonHiddenCup(canvasSize = 32, visibleColor = '#4caf50', hiddenColor = '#e0e0e0') {
11
+ const cx = Math.floor(canvasSize / 2);
12
+ const cy = Math.floor(canvasSize / 2);
13
+ const r = Math.floor(canvasSize * 0.25);
14
+ const h = Math.floor(canvasSize * 0.5);
15
+
16
+ return hiddenShapes.drawXRayCup(cx, cy, r, h, visibleColor, hiddenColor);
17
+ }
18
+
19
+ module.exports = { lessonHiddenCup };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Auto-extracted from hidden_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Hidden Head (Human head and skull)
8
+ * You don't see the whole skull, but must understand the structure behind it.
9
+ */
10
+ function lessonHiddenHead(canvasSize = 32, visibleColor = '#ff5722', hiddenColor = '#e0e0e0') {
11
+ const cx = Math.floor(canvasSize / 2);
12
+ const cy = Math.floor(canvasSize * 0.4);
13
+ const r = Math.floor(canvasSize * 0.25);
14
+
15
+ return hiddenShapes.drawXRayHead(cx, cy, r, visibleColor, hiddenColor);
16
+ }
17
+
18
+ module.exports = { lessonHiddenHead };
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * lessons/index.js — Art Tree: Lessons Index
4
+ *
5
+ * Exports all lesson functions and catalog getters organized by category.
6
+ */
7
+
8
+ const basic = require('./basic');
9
+ const advanced = require('./advanced');
10
+ const curves = require('./curves');
11
+ const ellipses = require('./ellipses');
12
+ const forms3d = require('./3d');
13
+ const structure = require('./structure');
14
+ const crossSections = require('./cross-sections');
15
+ const transforms = require('./transforms');
16
+ const surfaces = require('./surfaces');
17
+ const perspective = require('./perspective');
18
+ const hidden = require('./hidden');
19
+ const lighting = require('./lighting');
20
+ const materials = require('./materials');
21
+ const analysis = require('./analysis');
22
+ const layers = require('./layers');
23
+ const sky = require('./sky');
24
+
25
+ module.exports = {
26
+ ...basic,
27
+ ...advanced,
28
+ ...curves,
29
+ ...ellipses,
30
+ ...forms3d,
31
+ ...structure,
32
+ ...crossSections,
33
+ ...transforms,
34
+ ...surfaces,
35
+ ...perspective,
36
+ ...hidden,
37
+ ...lighting,
38
+ ...materials,
39
+ ...analysis,
40
+ ...layers,
41
+ ...sky,
42
+ };
@@ -1,4 +1,7 @@
1
- const layerShapes = require('./layer_shapes');
1
+ /**
2
+ * Auto-extracted from layer_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
2
5
 
3
6
  /**
4
7
  * Lesson: Layer Structure (Tư duy Layer)
@@ -15,18 +18,4 @@ function lessonLayerStep(canvasSize = 32, layerIndex = 1) {
15
18
  return layerShapes.drawLayeredCup(cx, cy, canvasSize, validLayer);
16
19
  }
17
20
 
18
- function getLayerLessonCatalog() {
19
- return [
20
- {
21
- id: 'layer_step',
22
- name: '7-Layer Painting Structure',
23
- description: 'View the contents of a specific layer of a Cup (1=Ref, 2=Sketch, 3=Construction, 4=Lineart, 5=Color, 6=Shadow, 7=Light)',
24
- fn: lessonLayerStep
25
- }
26
- ];
27
- }
28
-
29
- module.exports = {
30
- lessonLayerStep,
31
- getLayerLessonCatalog
32
- };
21
+ module.exports = { lessonLayerStep };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Auto-extracted from light_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Contact Shadow (Point of contact shadow)
8
+ * The darkest area where an object touches the ground.
9
+ */
10
+ function lessonContactShadow(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.3);
15
+
16
+ // Ground line
17
+ commands.push(shapes.drawLine(0, cy + r, canvasSize, cy + r, '#9e9e9e'));
18
+
19
+ // Sphere outline
20
+ commands.push(shapes.drawCircle(cx, cy, r, '#bdbdbd', false));
21
+
22
+ // Cast shadow (faint)
23
+ commands.push(shapes.drawEllipse(cx + Math.floor(r*0.5), cy + r, Math.floor(r*1.2), Math.floor(r*0.2), '#757575', true));
24
+
25
+ // CONTACT SHADOW (Pitch black, right at the touching point)
26
+ // Draw a very small, very dark ellipse directly under the center
27
+ commands.push(shapes.drawEllipse(cx, cy + r, Math.floor(r * 0.4), 2, '#000000', true));
28
+ commands.push(shapes.drawEllipse(cx, cy + r, Math.floor(r * 0.2), 1, '#000000', true));
29
+
30
+ return commands;
31
+ }
32
+
33
+ module.exports = { lessonContactShadow };