StepWise-Math-AI / examples /002-visual-proof-pythagorean-theorem.json
DreamyDetective's picture
feat: added application files
69ac033 verified
{
"appName": "VisualMath AI Export",
"exportedAt": "2025-11-24T20:58:36.471Z",
"input": {
"mode": "text",
"text": "explain pythagoras theroem"
},
"concept": {
"conceptTitle": "Pythagorean Theorem",
"educationalGoal": "To visually understand and prove the relationship between the sides of a right-angled triangle: a² + b² = c².",
"explanation": "The Pythagorean Theorem is a fundamental principle in geometry that describes the relationship between the three sides of a **right-angled triangle**. A right-angled triangle is a triangle with one angle measuring 90 degrees.\n\nLet's label the two shorter sides (legs) as `a` and `b`, and the longest side (hypotenuse), which is opposite the right angle, as `c`. The theorem states that the square of the hypotenuse (`c²`) is equal to the sum of the squares of the other two sides (`a² + b²`).\n\nWe'll explore a classic visual proof that demonstrates this relationship by rearranging shapes!",
"steps": [
{
"stepTitle": "1. Introducing the Right Triangle",
"instruction": "Observe the right-angled triangle. Its two shorter sides are labeled `a` and `b`, and the longest side, the hypotenuse, is labeled `c`. The square symbol marks the 90-degree angle.",
"visualFocus": "A single right-angled triangle with sides a, b, c labeled, and the right angle marked with a square."
},
{
"stepTitle": "2. Squares on the Sides",
"instruction": "Drag the slider to visualize the squares built on each side of the triangle. The area of each square corresponds to a², b², and c² respectively.",
"visualFocus": "The right triangle, with squares built outwards from each side (a, b, and c). The areas a², b², c² are displayed next to their respective squares."
},
{
"stepTitle": "3. Proof Setup: First Arrangement",
"instruction": "To prove a² + b² = c², we'll use a larger square with side length (a+b). Observe how four copies of our original right triangle are arranged inside this large square. They form a smaller square in the center.",
"visualFocus": "A large square (side a+b). Inside, four identical right triangles are arranged, forming a central square with side c. The central square and the four triangles should be distinct."
},
{
"stepTitle": "4. Area Calculation: First Arrangement",
"instruction": "The total area of the large square can be expressed as the sum of its internal parts: the central square and the four triangles. Click 'Next' to see the calculation.",
"visualFocus": "Text: 'Area_large = Area(central square) + Area(4 triangles)'. Then, 'Area_large = c² + 4 * (1/2 * a * b)' simplifies to 'Area_large = c² + 2ab'. The central square and triangles are highlighted during calculation."
},
{
"stepTitle": "5. Proof Setup: Second Arrangement",
"instruction": "Now, let's take the *exact same four triangles* and arrange them differently within a second identical large square (also with side a+b). This time, they form two smaller squares (a² and b²) and two rectangles.",
"visualFocus": "A second large square (side a+b) appears next to the first. Inside it, the four identical right triangles are rearranged to form a square of side 'a', a square of side 'b', and two rectangles of area 'ab' each. The a² and b² squares should be distinct."
},
{
"stepTitle": "6. Area Calculation: Second Arrangement",
"instruction": "Similar to before, the total area of this second large square can also be expressed as the sum of *its* internal parts. Click 'Next' to see the calculation.",
"visualFocus": "Text: 'Area_large = Area(square a) + Area(square b) + Area(2 rectangles)'. Then, 'Area_large = a² + b² + 2 * (a * b)' is displayed. The a² and b² squares and the 'ab' rectangles are highlighted during calculation."
},
{
"stepTitle": "7. The Conclusion",
"instruction": "Since both large squares have the same side length (a+b) and contain the exact same four triangles, their total areas must be equal. Equate the two expressions for the large square's area to reveal the Pythagorean Theorem!",
"visualFocus": "Display: 'c² + 2ab = a² + b² + 2ab'. Then, animate the cancellation of '2ab' from both sides, leaving: 'c² = a² + b²'. This final equation is highlighted prominently."
}
],
"visualSpec": {
"elements": [
"Right-angled triangle (vertices A, B, C; right angle at C)",
"Sides labeled: 'a' (opposite A), 'b' (opposite B), 'c' (opposite C - hypotenuse)",
"Squares built on sides a, b, c (areas a², b², c²)",
"Large square (side a+b)",
"Four identical right triangles (copies of the original)",
"Central square (side c) formed by the first arrangement of triangles",
"Two smaller squares (sides a, b) formed by the second arrangement of triangles",
"Two rectangles (dimensions a x b) formed by the second arrangement of triangles",
"Text labels for areas and equations"
],
"interactions": [
"Slider to control visibility/size of squares in Step 2",
"Next button to advance through steps and trigger animations/text reveals",
"Highlighting of specific visual elements (e.g., sides, squares, triangles) as they are discussed"
],
"mathLogic": "Area of a square = side * side; Area of a triangle = 1/2 * base * height; (a+b)² = a² + 2ab + b²; Equating areas: c² + 2ab = a² + b² + 2ab => c² = a² + b²"
}
},
"sourceCode": "\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Pythagorean Theorem Visual Proof</title>\n <style>\n :root {\n --bg-color: #0f172a;\n --panel-bg: #1e293b;\n --text-main: #e2e8f0;\n --text-muted: #94a3b8;\n --accent-blue: #3b82f6;\n --accent-red: #ef4444; /* Side a */\n --accent-green: #22c55e; /* Side b */\n --accent-yellow: #eab308;/* Side c */\n --btn-hover: #334155;\n }\n\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n body {\n font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n background-color: var(--bg-color);\n color: var(--text-main);\n height: 100vh;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* Header */\n header {\n padding: 1rem 1.5rem;\n border-bottom: 1px solid #334155;\n flex-shrink: 0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n h1 {\n font-size: 1.25rem;\n font-weight: 600;\n letter-spacing: 0.05em;\n }\n\n /* Main Layout */\n main {\n flex: 1;\n display: flex;\n flex-direction: row;\n overflow: hidden;\n }\n\n /* Canvas Area */\n #canvas-container {\n flex: 2;\n position: relative;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: #020617;\n overflow: hidden;\n }\n\n canvas {\n display: block;\n max-width: 100%;\n max-height: 100%;\n }\n\n /* Info & Controls Panel */\n #info-panel {\n flex: 1;\n min-width: 320px;\n max-width: 500px;\n background-color: var(--panel-bg);\n border-left: 1px solid #334155;\n display: flex;\n flex-direction: column;\n padding: 2rem;\n box-shadow: -5px 0 15px rgba(0,0,0,0.3);\n z-index: 10;\n }\n\n /* Text Content */\n .step-indicator {\n text-transform: uppercase;\n font-size: 0.75rem;\n color: var(--accent-blue);\n font-weight: bold;\n margin-bottom: 0.5rem;\n }\n\n h2 {\n font-size: 1.5rem;\n margin-bottom: 1rem;\n color: #fff;\n }\n\n p {\n line-height: 1.6;\n color: var(--text-muted);\n margin-bottom: 1.5rem;\n font-size: 1rem;\n }\n\n /* Math Display Area */\n .math-display {\n background: #0f172a;\n border: 1px solid #334155;\n border-radius: 8px;\n padding: 1.5rem;\n margin-bottom: auto; /* Push controls to bottom */\n font-family: 'Courier New', Courier, monospace;\n font-size: 1.1rem;\n text-align: center;\n min-height: 100px;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n transition: all 0.3s ease;\n }\n\n .math-line {\n margin: 5px 0;\n opacity: 0;\n transform: translateY(10px);\n animation: fadeInUp 0.5s forwards;\n }\n\n .highlight-eqn {\n color: var(--accent-yellow);\n font-weight: bold;\n font-size: 1.3rem;\n }\n\n .strike {\n text-decoration: line-through;\n text-decoration-color: var(--accent-red);\n text-decoration-thickness: 2px;\n opacity: 0.5;\n }\n\n /* Controls */\n .controls {\n margin-top: 2rem;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n }\n\n .slider-container {\n display: none; /* Hidden by default */\n width: 100%;\n margin-bottom: 1rem;\n }\n \n .slider-container label {\n display: block;\n margin-bottom: 0.5rem;\n font-size: 0.9rem;\n color: var(--text-muted);\n }\n\n input[type=range] {\n width: 100%;\n cursor: pointer;\n accent-color: var(--accent-blue);\n }\n\n .nav-buttons {\n display: flex;\n gap: 1rem;\n }\n\n button {\n flex: 1;\n padding: 0.75rem;\n border: none;\n border-radius: 6px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 1rem;\n }\n\n button.btn-primary {\n background-color: var(--accent-blue);\n color: white;\n }\n\n button.btn-primary:hover {\n background-color: #2563eb;\n }\n\n button.btn-secondary {\n background-color: #334155;\n color: var(--text-main);\n }\n\n button.btn-secondary:hover {\n background-color: #475569;\n }\n\n button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n /* Color Spans for Text */\n .c-a { color: var(--accent-red); font-weight: bold; }\n .c-b { color: var(--accent-green); font-weight: bold; }\n .c-c { color: var(--accent-yellow); font-weight: bold; }\n\n /* Animations */\n @keyframes fadeInUp {\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* Responsive */\n @media (max-width: 800px) {\n main {\n flex-direction: column;\n }\n \n #canvas-container {\n flex: 1;\n min-height: 50vh;\n }\n\n #info-panel {\n flex: 1;\n width: 100%;\n max-width: 100%;\n border-left: none;\n border-top: 1px solid #334155;\n padding: 1.5rem;\n }\n\n h2 { font-size: 1.2rem; }\n }\n </style>\n</head>\n<body>\n\n<header>\n <h1>MathVisuals <span style=\"color:var(--accent-blue)\">//</span> Pythagorean Theorem</h1>\n</header>\n\n<main>\n <div id=\"canvas-container\">\n <canvas id=\"vizCanvas\"></canvas>\n </div>\n\n <div id=\"info-panel\">\n <div>\n <div class=\"step-indicator\" id=\"step-indicator\">Step 1 of 7</div>\n <h2 id=\"step-title\">Introduction</h2>\n <div id=\"step-desc\"></div>\n </div>\n\n <div class=\"slider-container\" id=\"slider-group\">\n <label for=\"square-slider\">Resize Squares</label>\n <input type=\"range\" id=\"square-slider\" min=\"0\" max=\"1\" step=\"0.01\" value=\"0\">\n </div>\n\n <div class=\"math-display\" id=\"math-display\">\n <!-- Dynamic Math Content -->\n </div>\n\n <div class=\"controls\">\n <div class=\"nav-buttons\">\n <button id=\"prev-btn\" class=\"btn-secondary\">Previous</button>\n <button id=\"next-btn\" class=\"btn-primary\">Next</button>\n </div>\n </div>\n </div>\n</main>\n\n<script>\n/**\n * Pythagorean Theorem Visualization Logic\n */\n\n// Configuration\nconst COLORS = {\n bg: '#0f172a',\n a: '#ef4444',\n b: '#22c55e',\n c: '#eab308',\n tri: 'rgba(59, 130, 246, 0.6)', // Blue with opacity\n triStroke: '#60a5fa',\n text: '#e2e8f0',\n grid: '#1e293b'\n};\n\n// Triangle properties (Base unit logic)\n// We use a 3-4-5 triangle for clean integer visuals, but code handles generic.\nconst TRI = {\n a: 3, // vertical leg\n b: 4, // horizontal leg\n c: 5\n};\n\nconst STEPS = [\n {\n id: 0,\n title: \"Introducing the Right Triangle\",\n desc: `Here is a right-angled triangle. The two shorter sides are labeled <span class=\"c-a\">a</span> and <span class=\"c-b\">b</span>. The longest side, opposite the right angle, is the hypotenuse, labeled <span class=\"c-c\">c</span>.`,\n math: [],\n hasSlider: false\n },\n {\n id: 1,\n title: \"Squares on the Sides\",\n desc: `Drag the slider to build squares on each side. The area of each square is the side length squared: <span class=\"c-a\">a²</span>, <span class=\"c-b\">b²</span>, and <span class=\"c-c\">c²</span>.`,\n math: [],\n hasSlider: true\n },\n {\n id: 2,\n title: \"Proof Setup: First Arrangement\",\n desc: `Let's build a large square with side length <strong>(a + b)</strong>. Inside, we arrange four copies of our triangle. Notice the empty space in the center forms a tilted square of side <span class=\"c-c\">c</span>.`,\n math: [],\n hasSlider: false\n },\n {\n id: 3,\n title: \"Area Calculation: First Arrangement\",\n desc: `The total area is the sum of the inner parts: the central square <span class=\"c-c\">(c²)</span> and the four triangles.`,\n math: [\n `Area<sub>Total</sub> = Area(<span class=\"c-c\">Square C</span>) + Area(4 Triangles)`,\n `Area<sub>Total</sub> = <span class=\"c-c\">c²</span> + 4 × (½ × <span class=\"c-a\">a</span> × <span class=\"c-b\">b</span>)`,\n `Area<sub>Total</sub> = <span class=\"c-c\">c²</span> + 2<span class=\"c-a\">a</span><span class=\"c-b\">b</span>`\n ],\n hasSlider: false\n },\n {\n id: 4,\n title: \"Proof Setup: Second Arrangement\",\n desc: `Now, take a second identical large square (side <strong>a + b</strong>). We rearrange the <em>same four triangles</em> differently. This leaves two smaller squares: <span class=\"c-a\">a²</span> and <span class=\"c-b\">b²</span>.`,\n math: [],\n hasSlider: false\n },\n {\n id: 5,\n title: \"Area Calculation: Second Arrangement\",\n desc: `Again, calculate the total area. It is the sum of the two squares (<span class=\"c-a\">a²</span>, <span class=\"c-b\">b²</span>) and the four triangles (which form two rectangles).`,\n math: [\n `Area<sub>Total</sub> = Area(<span class=\"c-a\">Sq A</span>) + Area(<span class=\"c-b\">Sq B</span>) + Area(4 Triangles)`,\n `Area<sub>Total</sub> = <span class=\"c-a\">a²</span> + <span class=\"c-b\">b²</span> + 2 × (<span class=\"c-a\">a</span> × <span class=\"c-b\">b</span>)`,\n `Area<sub>Total</sub> = <span class=\"c-a\">a²</span> + <span class=\"c-b\">b²</span> + 2<span class=\"c-a\">a</span><span class=\"c-b\">b</span>`\n ],\n hasSlider: false\n },\n {\n id: 6,\n title: \"The Conclusion\",\n desc: `Since both large squares are the same size, their area formulas must be equal. We can cancel out the triangles (2ab) from both sides.`,\n math: [\n `<span class=\"c-c\">c²</span> + <span class=\"strike\">2ab</span> = <span class=\"c-a\">a²</span> + <span class=\"c-b\">b²</span> + <span class=\"strike\">2ab</span>`,\n `<span class=\"highlight-eqn\"><span class=\"c-c\">c²</span> = <span class=\"c-a\">a²</span> + <span class=\"c-b\">b²</span></span>`\n ],\n hasSlider: false\n }\n];\n\n// Application State\nlet currentState = {\n step: 0,\n sliderValue: 0, // 0 to 1\n canvasWidth: 0,\n canvasHeight: 0,\n pixelsPerUnit: 40 // Scale factor\n};\n\n// DOM Elements\nconst canvas = document.getElementById('vizCanvas');\nconst ctx = canvas.getContext('2d');\nconst stepTitle = document.getElementById('step-title');\nconst stepDesc = document.getElementById('step-desc');\nconst stepIndicator = document.getElementById('step-indicator');\nconst mathDisplay = document.getElementById('math-display');\nconst sliderGroup = document.getElementById('slider-group');\nconst slider = document.getElementById('square-slider');\nconst prevBtn = document.getElementById('prev-btn');\nconst nextBtn = document.getElementById('next-btn');\n\n// Initialization\nfunction init() {\n resizeCanvas();\n window.addEventListener('resize', resizeCanvas);\n \n prevBtn.addEventListener('click', () => changeStep(-1));\n nextBtn.addEventListener('click', () => changeStep(1));\n \n slider.addEventListener('input', (e) => {\n currentState.sliderValue = parseFloat(e.target.value);\n draw();\n });\n\n updateUI();\n draw();\n}\n\nfunction resizeCanvas() {\n const container = document.getElementById('canvas-container');\n canvas.width = container.clientWidth;\n canvas.height = container.clientHeight;\n currentState.canvasWidth = canvas.width;\n currentState.canvasHeight = canvas.height;\n \n // Calculate scale based on a+b+padding\n const totalUnits = TRI.a + TRI.b + 2; // +2 for padding\n const minDim = Math.min(canvas.width, canvas.height);\n currentState.pixelsPerUnit = (minDim * 0.8) / totalUnits;\n \n draw();\n}\n\nfunction changeStep(delta) {\n const newStep = currentState.step + delta;\n if (newStep >= 0 && newStep < STEPS.length) {\n currentState.step = newStep;\n \n // Reset slider for step 2 interactions\n if (newStep === 1) {\n currentState.sliderValue = 0;\n slider.value = 0;\n } else {\n currentState.sliderValue = 1; // Full visualization for other steps\n }\n\n updateUI();\n draw();\n }\n}\n\nfunction updateUI() {\n const stepData = STEPS[currentState.step];\n \n // Text Updates\n stepIndicator.textContent = `Step ${stepData.id + 1} of ${STEPS.length}`;\n stepTitle.textContent = stepData.title;\n stepDesc.innerHTML = stepData.desc;\n \n // Math Display\n mathDisplay.innerHTML = '';\n stepData.math.forEach((line, index) => {\n const div = document.createElement('div');\n div.className = 'math-line';\n div.style.animationDelay = `${index * 0.5}s`;\n div.innerHTML = line;\n mathDisplay.appendChild(div);\n });\n\n // Controls Visibility\n sliderGroup.style.display = stepData.hasSlider ? 'block' : 'none';\n \n // Button States\n prevBtn.disabled = currentState.step === 0;\n nextBtn.disabled = currentState.step === STEPS.length - 1;\n}\n\n// --- Drawing Functions ---\n\nfunction draw() {\n // Clear Canvas\n ctx.fillStyle = COLORS.bg;\n ctx.fillRect(0, 0, currentState.canvasWidth, currentState.canvasHeight);\n \n ctx.save();\n \n // Center the coordinate system\n ctx.translate(currentState.canvasWidth / 2, currentState.canvasHeight / 2);\n \n const ppu = currentState.pixelsPerUnit;\n const { a, b, c } = TRI;\n \n // Switch based on step\n switch (currentState.step) {\n case 0: // Intro\n case 1: // Slider Squares\n drawSingleTriangleScene(ppu, a, b, c);\n break;\n \n case 2: // Arr 1 Setup\n case 3: // Arr 1 Calc\n case 6: // Conclusion (Comparing, usually shows Arr 1 or equation emphasis. Let's show Arr 1)\n drawArrangementOne(ppu, a, b, c);\n break;\n\n case 4: // Arr 2 Setup\n case 5: // Arr 2 Calc\n drawArrangementTwo(ppu, a, b, c);\n break;\n }\n\n ctx.restore();\n}\n\nfunction drawSingleTriangleScene(ppu, a, b, c) {\n // Center the triangle roughly\n const offsetX = -(b * ppu) / 2;\n const offsetY = (a * ppu) / 2;\n ctx.translate(offsetX, offsetY);\n\n // Draw Squares if Slider is active\n if (currentState.step === 1) {\n const t = currentState.sliderValue;\n \n // Square A (Left side)\n ctx.fillStyle = COLORS.a;\n ctx.globalAlpha = 0.2 + (0.6 * t);\n // Grow out to left: x from 0 to -a*t, width a*t\n // Actually simpler: Draw full square, scale it, or mask it.\n // Let's just scale the size of the square based on t\n const sA = a * ppu * t;\n if (sA > 1) {\n ctx.fillRect(-sA, -a * ppu, sA, sA); // Left of A leg\n ctx.globalAlpha = 1;\n if(t > 0.8) drawLabel(\"a²\", -sA/2, -a*ppu/2, COLORS.text);\n }\n\n // Square B (Bottom side)\n ctx.fillStyle = COLORS.b;\n ctx.globalAlpha = 0.2 + (0.6 * t);\n const sB = b * ppu * t;\n if (sB > 1) {\n ctx.fillRect(0, 0, sB, sB); // Below B leg\n ctx.globalAlpha = 1;\n if(t > 0.8) drawLabel(\"b²\", sB/2, sB/2, COLORS.text);\n }\n\n // Square C (Hypotenuse)\n ctx.save();\n // Rotate to align with hypotenuse\n // Angle of hypotenuse relative to x-axis (A is top (0, -a*ppu), B is right (b*ppu, 0))\n // Vector AB = (b, a). Angle = atan(a/b)\n const angle = Math.atan(a/b);\n // Move to top point\n ctx.translate(0, -a * ppu);\n ctx.rotate(angle); \n // Square projects \"up\" from the line A-B relative to the triangle? \n // Normal is perpendicular. \n // Let's simplify: Hypotenuse connects (0, -a) and (b, 0).\n // We want the square to grow outwards.\n ctx.fillStyle = COLORS.c;\n ctx.globalAlpha = 0.2 + (0.6 * t);\n const sC = c * ppu * t;\n if (sC > 1) {\n ctx.fillRect(0, -sC, c * ppu, sC);\n ctx.globalAlpha = 1;\n if(t > 0.8) {\n ctx.save();\n ctx.translate(c*ppu/2, -sC/2);\n ctx.rotate(-angle); // Unrotate text\n drawLabel(\"c²\", 0, 0, COLORS.text);\n ctx.restore();\n }\n }\n ctx.restore();\n }\n\n // Draw Triangle\n drawRightTriangle(ctx, 0, 0, a * ppu, b * ppu, COLORS.tri);\n \n // Labels\n ctx.font = \"bold 16px sans-serif\";\n \n // Side a\n ctx.fillStyle = COLORS.a;\n ctx.fillText(\"a\", -20, - (a * ppu) / 2);\n \n // Side b\n ctx.fillStyle = COLORS.b;\n ctx.fillText(\"b\", (b * ppu) / 2, 20);\n \n // Side c\n ctx.fillStyle = COLORS.c;\n ctx.fillText(\"c\", (b * ppu) / 2 + 10, - (a * ppu) / 2 - 10);\n}\n\nfunction drawArrangementOne(ppu, a, b, c) {\n const size = (a + b) * ppu;\n const startX = -size / 2;\n const startY = -size / 2;\n\n // Draw Big Square Container\n ctx.strokeStyle = COLORS.text;\n ctx.lineWidth = 2;\n ctx.strokeRect(startX, startY, size, size);\n\n // 4 Triangles\n const triColor = COLORS.tri;\n\n // Top-Left Triangle\n drawRightTriangleStandard(ctx, startX, startY, b*ppu, a*ppu, triColor, 0); // Base b, Height a ?? \n // Actually, standard proof:\n // Top-left corner: Go right 'b', down 'a' -> Hypotenuse c\n // Top-Right corner: Go down 'b', left 'a'\n \n // Let's do the standard coordinates explicitly for clarity\n // 1. Top Left (Rotated 0) - Vertical side 'a' on left wall, horizontal 'b' on top wall\n // Wait, if a=3, b=4.\n // Top Left Triangle: Vertices at (startX, startY), (startX + a, startY), (startX, startY + b). Hypotenuse internal.\n // No, the arrangement that forms C^2 in center:\n // T1: Top-Left corner. Leg 'a' along top edge. Leg 'b' along left edge. \n // T2: Top-Right corner. Leg 'b' along top edge. Leg 'a' along right edge.\n // ... This forms a small square (b-a) in center. Not c^2.\n \n // Correct Arrangement for C^2 in center (Bhaskara / Chinese):\n // T1: Base b along bottom, Height a along left. (Bottom-Left)\n // T2: Base b along top, Height a along right. (Top-Right)\n // T3: Base b along right... \n // \n // Let's use the outer square method:\n // Square side (a+b).\n // Point P1 on Top Edge at distance 'a' from TopLeft.\n // Point P2 on Right Edge at distance 'a' from TopRight.\n // Point P3 on Bottom Edge at distance 'a' from BottomRight.\n // Point P4 on Left Edge at distance 'a' from BottomLeft.\n // Connect P1-P2-P3-P4 -> This forms Square C.\n // The corners are the 4 triangles.\n \n const sa = a * ppu;\n const sb = b * ppu;\n \n // Triangle 1 (Top Left corner)\n // Vertices: (startX, startY), (startX+sa, startY), (startX, startY+sb). \n // This creates hypotenuse length c. \n // Let's fill the corners.\n \n // Corner 1: Top Left. Width 'a', Height 'b'.\n drawTrianglePoly(ctx, startX, startY, startX + sa, startY, startX, startY + sb, triColor);\n \n // Corner 2: Top Right. Width 'b', Height 'a'.\n drawTrianglePoly(ctx, startX + size, startY, startX + size - sb, startY, startX + size, startY + sa, triColor);\n\n // Corner 3: Bottom Right. Width 'a', Height 'b'.\n drawTrianglePoly(ctx, startX + size, startY + size, startX + size - sa, startY + size, startX + size, startY + size - sb, triColor);\n\n // Corner 4: Bottom Left. Width 'b', Height 'a'.\n drawTrianglePoly(ctx, startX, startY + size, startX + sb, startY + size, startX, startY + size - sa, triColor);\n\n // Label Center Square\n ctx.fillStyle = COLORS.c;\n ctx.globalAlpha = 0.2;\n ctx.beginPath();\n ctx.moveTo(startX + sa, startY);\n ctx.lineTo(startX + size, startY + sa);\n ctx.lineTo(startX + size - sa, startY + size);\n ctx.lineTo(startX, startY + size - sa);\n ctx.closePath();\n ctx.fill();\n \n ctx.globalAlpha = 1;\n drawLabel(\"c²\", 0, 0, COLORS.c);\n\n // Draw Side Labels on the outer box\n ctx.fillStyle = COLORS.text;\n ctx.font = \"14px sans-serif\";\n // Top Edge\n ctx.fillText(\"a\", startX + sa/2, startY - 10);\n ctx.fillText(\"b\", startX + sa + sb/2, startY - 10);\n}\n\nfunction drawArrangementTwo(ppu, a, b, c) {\n const size = (a + b) * ppu;\n const startX = -size / 2;\n const startY = -size / 2;\n const sa = a * ppu;\n const sb = b * ppu;\n\n // Outer Box\n ctx.strokeStyle = COLORS.text;\n ctx.lineWidth = 2;\n ctx.strokeRect(startX, startY, size, size);\n\n const triColor = COLORS.tri;\n\n // In this arrangement, we form a square a^2 and b^2.\n // Usually a^2 is top-left, b^2 is bottom-right.\n // The rectangles (a*b) are top-right and bottom-left.\n // Each rectangle is split into two triangles.\n\n // Square a^2 (Top Left)\n ctx.fillStyle = COLORS.a;\n ctx.globalAlpha = 0.3;\n ctx.fillRect(startX, startY, sa, sa);\n ctx.globalAlpha = 1;\n drawLabel(\"a²\", startX + sa/2, startY + sa/2, COLORS.text);\n\n // Square b^2 (Bottom Right)\n ctx.fillStyle = COLORS.b;\n ctx.globalAlpha = 0.3;\n ctx.fillRect(startX + sa, startY + sa, sb, sb);\n ctx.globalAlpha = 1;\n drawLabel(\"b²\", startX + sa + sb/2, startY + sa + sb/2, COLORS.text);\n\n // Rectangle 1 (Top Right) - Split into 2 triangles\n // Coords: x: startX+sa, y: startY, w: sb, h: sa\n drawTrianglePoly(ctx, startX + sa, startY, startX + size, startY, startX + size, startY + sa, triColor); // Top half\n drawTrianglePoly(ctx, startX + sa, startY, startX + sa, startY + sa, startX + size, startY + sa, triColor); // Bottom half\n // Draw diagonal line to show separation\n ctx.beginPath();\n ctx.moveTo(startX + sa, startY);\n ctx.lineTo(startX + size, startY + sa);\n ctx.strokeStyle = COLORS.bg;\n ctx.lineWidth = 1;\n ctx.stroke();\n\n // Rectangle 2 (Bottom Left) - Split into 2 triangles\n // Coords: x: startX, y: startY+sa, w: sa, h: sb\n drawTrianglePoly(ctx, startX, startY + sa, startX + sa, startY + sa, startX + sa, startY + size, triColor);\n drawTrianglePoly(ctx, startX, startY + sa, startX, startY + size, startX + sa, startY + size, triColor);\n // Draw diagonal\n ctx.beginPath();\n ctx.moveTo(startX, startY + sa);\n ctx.lineTo(startX + sa, startY + size);\n ctx.strokeStyle = COLORS.bg;\n ctx.lineWidth = 1;\n ctx.stroke();\n\n // Labels for sides\n ctx.fillStyle = COLORS.text;\n ctx.fillText(\"a\", startX + sa/2, startY - 10);\n ctx.fillText(\"b\", startX - 15, startY + sa + sb/2);\n}\n\n// --- Helpers ---\n\n// Draws triangle with right-angle at (x,y), vertical leg h (up negative), horizontal w (right positive)\nfunction drawRightTriangle(ctx, x, y, heightPixels, widthPixels, color) {\n ctx.beginPath();\n ctx.moveTo(x, y); // C (Right Angle)\n ctx.lineTo(x, y - heightPixels); // A\n ctx.lineTo(x + widthPixels, y); // B\n ctx.closePath();\n \n ctx.fillStyle = color;\n ctx.fill();\n ctx.strokeStyle = COLORS.triStroke;\n ctx.lineWidth = 2;\n ctx.stroke();\n\n // Right angle marker\n const m = 15;\n ctx.beginPath();\n ctx.moveTo(x, y - m);\n ctx.lineTo(x + m, y - m);\n ctx.lineTo(x + m, y);\n ctx.strokeStyle = COLORS.text;\n ctx.lineWidth = 1;\n ctx.stroke();\n}\n\n// Generic Triangle Polygon\nfunction drawTrianglePoly(ctx, x1, y1, x2, y2, x3, y3, color) {\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.lineTo(x3, y3);\n ctx.closePath();\n ctx.fillStyle = color;\n ctx.fill();\n ctx.strokeStyle = COLORS.bg; // Separator\n ctx.lineWidth = 1;\n ctx.stroke();\n}\n\n// Standard visual placeholder\nfunction drawRightTriangleStandard(ctx, x, y, w, h, color, rotationDeg) {\n ctx.save();\n ctx.translate(x, y);\n ctx.rotate(rotationDeg * Math.PI / 180);\n drawRightTriangle(ctx, 0, 0, h, w, color);\n ctx.restore();\n}\n\nfunction drawLabel(text, x, y, color) {\n ctx.fillStyle = color;\n ctx.font = \"bold 20px Courier New\";\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n ctx.fillText(text, x, y);\n}\n\n// Start\ninit();\n\n</script>\n</body>\n</html>\n"
}