Skip to content
LAM
Read Home Blog
Make Projects HTML Tools Games
Touch grass Notes Resume Links
Home Blog HTML Projects
Tools Games Notes Resume Links
Back Calc 2: 8-Bit Edition Math
Download Open
Show description 1,592 chars · Math

Calc 2: 8-Bit Edition

Calc 2: 8-Bit Edition




CALC 2: PARAMETRIC & POLAR



PARAMETRIC CURVES

PARAMETRIC CALCULUS

POLAR COORDINATES

POLAR AREAS & LENGTHS






PARAMETRIC EQUATIONS


x = f(t)
y = g(t)
where t is the parameter






CONVERSION FORMULAS


Parametric → Cartesian:
Eliminate t from both equations

Example: x = t², y = 2t
t = y/2, so x = (y/2)² = y²/4












TIME: t

t = 6.28





ANIMATION SPEED

Speed: 1.0x





CIRCLE
LISSAJOUS
ASTROID
SPIRAL








CURRENT CURVE: Circle
EQUATIONS: x = cos(t), y = sin(t)







TANGENT LINE


dy/dx = (dy/dt)/(dx/dt)

Tangent line at t = t₀:
y - y₀ = (dy/dx)|ₜ₌ₜ₀ · (x - x₀)






ARC LENGTH


L = ∫ᵃᵇ √[(dx/dt)² + (dy/dt)²] dt

where a ≤ t ≤ b












POINT: t₀

t₀ = 1.57





SHOW TANGENT





SHOW ARC LENGTH









TANGENT SLOPE: 0
ARC LENGTH (0 to t₀): 0







POLAR COORDINATES


r = distance from origin
θ = angle from positive x-axis

Point: (r, θ)






CONVERSION FORMULAS


Polar → Cartesian:
x = r cos(θ)
y = r sin(θ)

Cartesian → Polar:
r = √(x² + y²)
θ = arctan(y/x)












ANGLE: θ

θ = 6.28





CIRCLE
CARDIOID
ROSE
SPIRAL








CURRENT CURVE: Circle
EQUATION: r = 2







AREA IN POLAR


A = (1/2) ∫ᵃᵇ r² dθ

where α ≤ θ ≤ β






ARC LENGTH IN POLAR


L = ∫ᵃᵇ √[r² + (dr/dθ)²] dθ

where α ≤ θ ≤ β












START ANGLE: α

α = 0





END ANGLE: β

β = 3.14





SHOW AREA









AREA: 0
ARC LENGTH: 0

Calc 2: 8-Bit Edition

34,144 bytes · HTML source
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Calc 2: 8-Bit Edition</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
        
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        
        body {
            font-family: 'Press Start 2P', cursive;
            background: #1a1a2e;
            color: #eee;
            line-height: 1.6;
            overflow-x: hidden;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        
        h1 {
            text-align: center;
            color: #00ff00;
            font-size: 24px;
            margin-bottom: 30px;
            text-shadow: 3px 3px 0px #008800;
            animation: pulse 2s infinite;
        }
        
        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.8; }
        }
        
        .tabs {
            display: flex;
            gap: 10px;
            margin-bottom: 30px;
            flex-wrap: wrap;
        }
        
        .tab {
            background: #16213e;
            border: 3px solid #0f3460;
            padding: 10px 20px;
            cursor: pointer;
            font-size: 10px;
            transition: all 0.3s;
            position: relative;
        }
        
        .tab:hover {
            background: #0f3460;
            transform: translateY(-2px);
        }
        
        .tab.active {
            background: #e94560;
            border-color: #ff6b6b;
            box-shadow: 0 5px 0 #a01e3e;
        }
        
        .content {
            display: none;
            background: #16213e;
            border: 3px solid #0f3460;
            padding: 30px;
            min-height: 600px;
        }
        
        .content.active {
            display: block;
        }
        
        .formula-box {
            background: #0f3460;
            border: 2px solid #00ff00;
            padding: 20px;
            margin: 20px 0;
            font-size: 10px;
            box-shadow: 5px 5px 0 #000;
        }
        
        .formula-title {
            color: #00ff00;
            margin-bottom: 10px;
            font-size: 12px;
        }
        
        .formula {
            color: #fff;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            line-height: 1.8;
            letter-spacing: 1px;
        }
        
        .visualization {
            display: flex;
            gap: 30px;
            margin: 30px 0;
            flex-wrap: wrap;
        }
        
        .canvas-container {
            flex: 1;
            min-width: 400px;
        }
        
        canvas {
            border: 3px solid #00ff00;
            background: #000;
            width: 100%;
            max-width: 500px;
            height: 400px;
            image-rendering: pixelated;
            box-shadow: 5px 5px 0 #008800;
        }
        
        .controls {
            flex: 1;
            min-width: 300px;
        }
        
        .control-group {
            margin: 20px 0;
            background: #0f3460;
            padding: 15px;
            border: 2px solid #00ff00;
        }
        
        .control-label {
            display: block;
            margin-bottom: 10px;
            font-size: 10px;
            color: #00ff00;
        }
        
        input[type="range"] {
            width: 100%;
            height: 20px;
            background: #000;
            outline: none;
            border: 2px solid #00ff00;
            cursor: pointer;
            -webkit-appearance: none;
        }
        
        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 20px;
            height: 20px;
            background: #00ff00;
            border: 2px solid #000;
            cursor: pointer;
        }
        
        .value-display {
            text-align: right;
            color: #fff;
            font-size: 10px;
            margin-top: 5px;
        }
        
        .example-buttons {
            display: flex;
            gap: 10px;
            margin: 20px 0;
            flex-wrap: wrap;
        }
        
        .example-btn {
            background: #e94560;
            border: 2px solid #ff6b6b;
            color: #fff;
            padding: 10px 15px;
            cursor: pointer;
            font-size: 9px;
            font-family: 'Press Start 2P', cursive;
            transition: all 0.3s;
        }
        
        .example-btn:hover {
            background: #ff6b6b;
            transform: translateY(-2px);
        }
        
        .info-text {
            font-size: 10px;
            line-height: 2;
            margin: 20px 0;
            background: #0f3460;
            padding: 15px;
            border-left: 5px solid #00ff00;
        }
        
        @media (max-width: 768px) {
            .tabs {
                justify-content: center;
            }
            
            .visualization {
                flex-direction: column;
            }
            
            canvas {
                max-width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>CALC 2: PARAMETRIC & POLAR</h1>
        
        <div class="tabs">
            <div class="tab active" data-tab="parametric">PARAMETRIC CURVES</div>
            <div class="tab" data-tab="parametric-calc">PARAMETRIC CALCULUS</div>
            <div class="tab" data-tab="polar">POLAR COORDINATES</div>
            <div class="tab" data-tab="polar-calc">POLAR AREAS & LENGTHS</div>
        </div>
        
        <div class="content active" id="parametric">
            <div class="formula-box">
                <div class="formula-title">PARAMETRIC EQUATIONS</div>
                <div class="formula">
                    x = f(t)<br>
                    y = g(t)<br><br>
                    where t is the parameter
                </div>
            </div>
            
            <div class="formula-box">
                <div class="formula-title">CONVERSION FORMULAS</div>
                <div class="formula">
                    Parametric → Cartesian:<br>
                    Eliminate t from both equations<br><br>
                    
                    Example: x = t², y = 2t<br>
                    t = y/2, so x = (y/2)² = y²/4
                </div>
            </div>
            
            <div class="visualization">
                <div class="canvas-container">
                    <canvas id="parametricCanvas"></canvas>
                </div>
                <div class="controls">
                    <div class="control-group">
                        <label class="control-label">TIME: t</label>
                        <input type="range" id="tRange" min="0" max="6.28" step="0.01" value="6.28">
                        <div class="value-display" id="tValue">t = 6.28</div>
                    </div>
                    
                    <div class="control-group">
                        <label class="control-label">ANIMATION SPEED</label>
                        <input type="range" id="speedRange" min="0" max="5" step="0.1" value="1">
                        <div class="value-display" id="speedValue">Speed: 1.0x</div>
                    </div>
                    
                    <div class="example-buttons">
                        <button class="example-btn" onclick="setParametricExample('circle')">CIRCLE</button>
                        <button class="example-btn" onclick="setParametricExample('lissajous')">LISSAJOUS</button>
                        <button class="example-btn" onclick="setParametricExample('astroid')">ASTROID</button>
                        <button class="example-btn" onclick="setParametricExample('spiral')">SPIRAL</button>
                    </div>
                </div>
            </div>
            
            <div class="info-text">
                CURRENT CURVE: <span id="currentParametric">Circle</span><br>
                EQUATIONS: <span id="parametricEquations">x = cos(t), y = sin(t)</span>
            </div>
        </div>
        
        <div class="content" id="parametric-calc">
            <div class="formula-box">
                <div class="formula-title">TANGENT LINE</div>
                <div class="formula">
                    dy/dx = (dy/dt)/(dx/dt)<br><br>
                    
                    Tangent line at t = t₀:<br>
                    y - y₀ = (dy/dx)|ₜ₌ₜ₀ · (x - x₀)
                </div>
            </div>
            
            <div class="formula-box">
                <div class="formula-title">ARC LENGTH</div>
                <div class="formula">
                    L = ∫ᵃᵇ √[(dx/dt)² + (dy/dt)²] dt<br><br>
                    
                    where a ≤ t ≤ b
                </div>
            </div>
            
            <div class="visualization">
                <div class="canvas-container">
                    <canvas id="parametricCalcCanvas"></canvas>
                </div>
                <div class="controls">
                    <div class="control-group">
                        <label class="control-label">POINT: t₀</label>
                        <input type="range" id="t0Range" min="0" max="6.28" step="0.01" value="1.57">
                        <div class="value-display" id="t0Value">t₀ = 1.57</div>
                    </div>
                    
                    <div class="control-group">
                        <label class="control-label">SHOW TANGENT</label>
                        <input type="checkbox" id="showTangent" checked>
                    </div>
                    
                    <div class="control-group">
                        <label class="control-label">SHOW ARC LENGTH</label>
                        <input type="checkbox" id="showArcLength" checked>
                    </div>
                </div>
            </div>
            
            <div class="info-text">
                TANGENT SLOPE: <span id="tangentSlope">0</span><br>
                ARC LENGTH (0 to t₀): <span id="arcLength">0</span>
            </div>
        </div>
        
        <div class="content" id="polar">
            <div class="formula-box">
                <div class="formula-title">POLAR COORDINATES</div>
                <div class="formula">
                    r = distance from origin<br>
                    θ = angle from positive x-axis<br><br>
                    
                    Point: (r, θ)
                </div>
            </div>
            
            <div class="formula-box">
                <div class="formula-title">CONVERSION FORMULAS</div>
                <div class="formula">
                    Polar → Cartesian:<br>
                    x = r cos(θ)<br>
                    y = r sin(θ)<br><br>
                    
                    Cartesian → Polar:<br>
                    r = √(x² + y²)<br>
                    θ = arctan(y/x)
                </div>
            </div>
            
            <div class="visualization">
                <div class="canvas-container">
                    <canvas id="polarCanvas"></canvas>
                </div>
                <div class="controls">
                    <div class="control-group">
                        <label class="control-label">ANGLE: θ</label>
                        <input type="range" id="thetaRange" min="0" max="12.56" step="0.01" value="6.28">
                        <div class="value-display" id="thetaValue">θ = 6.28</div>
                    </div>
                    
                    <div class="example-buttons">
                        <button class="example-btn" onclick="setPolarExample('circle')">CIRCLE</button>
                        <button class="example-btn" onclick="setPolarExample('cardioid')">CARDIOID</button>
                        <button class="example-btn" onclick="setPolarExample('rose')">ROSE</button>
                        <button class="example-btn" onclick="setPolarExample('spiral')">SPIRAL</button>
                    </div>
                </div>
            </div>
            
            <div class="info-text">
                CURRENT CURVE: <span id="currentPolar">Circle</span><br>
                EQUATION: <span id="polarEquation">r = 2</span>
            </div>
        </div>
        
        <div class="content" id="polar-calc">
            <div class="formula-box">
                <div class="formula-title">AREA IN POLAR</div>
                <div class="formula">
                    A = (1/2) ∫ᵃᵇ r² dθ<br><br>
                    
                    where α ≤ θ ≤ β
                </div>
            </div>
            
            <div class="formula-box">
                <div class="formula-title">ARC LENGTH IN POLAR</div>
                <div class="formula">
                    L = ∫ᵃᵇ √[r² + (dr/dθ)²] dθ<br><br>
                    
                    where α ≤ θ ≤ β
                </div>
            </div>
            
            <div class="visualization">
                <div class="canvas-container">
                    <canvas id="polarCalcCanvas"></canvas>
                </div>
                <div class="controls">
                    <div class="control-group">
                        <label class="control-label">START ANGLE: α</label>
                        <input type="range" id="alphaRange" min="0" max="6.28" step="0.01" value="0">
                        <div class="value-display" id="alphaValue">α = 0</div>
                    </div>
                    
                    <div class="control-group">
                        <label class="control-label">END ANGLE: β</label>
                        <input type="range" id="betaRange" min="0" max="6.28" step="0.01" value="3.14">
                        <div class="value-display" id="betaValue">β = 3.14</div>
                    </div>
                    
                    <div class="control-group">
                        <label class="control-label">SHOW AREA</label>
                        <input type="checkbox" id="showArea" checked>
                    </div>
                </div>
            </div>
            
            <div class="info-text">
                AREA: <span id="polarArea">0</span><br>
                ARC LENGTH: <span id="polarArcLength">0</span>
            </div>
        </div>
    </div>
    
    <script>
        // Tab functionality
        const tabs = document.querySelectorAll('.tab');
        const contents = document.querySelectorAll('.content');
        
        tabs.forEach(tab => {
            tab.addEventListener('click', () => {
                const targetId = tab.dataset.tab;
                
                tabs.forEach(t => t.classList.remove('active'));
                contents.forEach(c => c.classList.remove('active'));
                
                tab.classList.add('active');
                document.getElementById(targetId).classList.add('active');
                
                // Initialize the canvas for the active tab
                initializeCanvas(targetId);
            });
        });
        
        // Canvas setup
        const canvases = {
            parametric: document.getElementById('parametricCanvas'),
            parametricCalc: document.getElementById('parametricCalcCanvas'),
            polar: document.getElementById('polarCanvas'),
            polarCalc: document.getElementById('polarCalcCanvas')
        };
        
        const contexts = {};
        Object.keys(canvases).forEach(key => {
            contexts[key] = canvases[key].getContext('2d');
            canvases[key].width = 500;
            canvases[key].height = 400;
        });
        
        // Animation variables
        let animationFrames = {};
        let parametricType = 'circle';
        let polarType = 'circle';
        
        // Parametric curves
        const parametricCurves = {
            circle: {
                name: 'Circle',
                equations: 'x = cos(t), y = sin(t)',
                x: t => Math.cos(t),
                y: t => Math.sin(t),
                tMax: 2 * Math.PI
            },
            lissajous: {
                name: 'Lissajous Curve',
                equations: 'x = sin(3t), y = sin(2t)',
                x: t => Math.sin(3 * t),
                y: t => Math.sin(2 * t),
                tMax: 2 * Math.PI
            },
            astroid: {
                name: 'Astroid',
                equations: 'x = cos³(t), y = sin³(t)',
                x: t => Math.pow(Math.cos(t), 3),
                y: t => Math.pow(Math.sin(t), 3),
                tMax: 2 * Math.PI
            },
            spiral: {
                name: 'Spiral',
                equations: 'x = t·cos(t)/4, y = t·sin(t)/4',
                x: t => t * Math.cos(t) / 4,
                y: t => t * Math.sin(t) / 4,
                tMax: 4 * Math.PI
            }
        };
        
        // Polar curves
        const polarCurves = {
            circle: {
                name: 'Circle',
                equation: 'r = 2',
                r: theta => 2,
                thetaMax: 2 * Math.PI
            },
            cardioid: {
                name: 'Cardioid',
                equation: 'r = 1 + cos(θ)',
                r: theta => 1 + Math.cos(theta),
                thetaMax: 2 * Math.PI
            },
            rose: {
                name: 'Four-Petaled Rose',
                equation: 'r = 2·cos(2θ)',
                r: theta => 2 * Math.cos(2 * theta),
                thetaMax: 2 * Math.PI
            },
            spiral: {
                name: 'Archimedean Spiral',
                equation: 'r = θ/2',
                r: theta => theta / 2,
                thetaMax: 4 * Math.PI
            }
        };
        
        // Drawing functions
        function drawGrid(ctx) {
            ctx.strokeStyle = '#003300';
            ctx.lineWidth = 1;
            
            // Grid lines
            for (let i = 0; i <= 10; i++) {
                const x = i * 50;
                const y = i * 40;
                
                ctx.beginPath();
                ctx.moveTo(x, 0);
                ctx.lineTo(x, 400);
                ctx.stroke();
                
                ctx.beginPath();
                ctx.moveTo(0, y);
                ctx.lineTo(500, y);
                ctx.stroke();
            }
            
            // Axes
            ctx.strokeStyle = '#00ff00';
            ctx.lineWidth = 2;
            
            ctx.beginPath();
            ctx.moveTo(250, 0);
            ctx.lineTo(250, 400);
            ctx.stroke();
            
            ctx.beginPath();
            ctx.moveTo(0, 200);
            ctx.lineTo(500, 200);
            ctx.stroke();
        }
        
        function toScreenCoords(x, y, scale = 80) {
            return {
                x: 250 + x * scale,
                y: 200 - y * scale
            };
        }
        
        // Parametric curve animation
        function animateParametric() {
            const ctx = contexts.parametric;
            const t = parseFloat(document.getElementById('tRange').value);
            const speed = parseFloat(document.getElementById('speedRange').value);
            const curve = parametricCurves[parametricType];
            
            ctx.clearRect(0, 0, 500, 400);
            drawGrid(ctx);
            
            // Draw curve
            ctx.strokeStyle = '#00ff00';
            ctx.lineWidth = 2;
            ctx.beginPath();
            
            const steps = 1000;
            const dt = t / steps;
            
            for (let i = 0; i <= steps; i++) {
                const ti = i * dt;
                const x = curve.x(ti);
                const y = curve.y(ti);
                const screen = toScreenCoords(x, y);
                
                if (i === 0) {
                    ctx.moveTo(screen.x, screen.y);
                } else {
                    ctx.lineTo(screen.x, screen.y);
                }
            }
            ctx.stroke();
            
            // Draw current point
            const currentX = curve.x(t);
            const currentY = curve.y(t);
            const currentScreen = toScreenCoords(currentX, currentY);
            
            ctx.fillStyle = '#ff0000';
            ctx.fillRect(currentScreen.x - 4, currentScreen.y - 4, 8, 8);
            
            // Auto-advance animation
            if (speed > 0 && t < curve.tMax) {
                document.getElementById('tRange').value = Math.min(t + 0.02 * speed, curve.tMax);
                document.getElementById('tValue').textContent = `t = ${document.getElementById('tRange').value}`;
            } else if (speed > 0 && t >= curve.tMax) {
                document.getElementById('tRange').value = 0;
            }
            
            animationFrames.parametric = requestAnimationFrame(animateParametric);
        }
        
        // Parametric calculus visualization
        function animateParametricCalc() {
            const ctx = contexts.parametricCalc;
            const t0 = parseFloat(document.getElementById('t0Range').value);
            const showTangent = document.getElementById('showTangent').checked;
            const showArcLength = document.getElementById('showArcLength').checked;
            const curve = parametricCurves.circle; // Using circle for calc demo
            
            ctx.clearRect(0, 0, 500, 400);
            drawGrid(ctx);
            
            // Draw full curve
            ctx.strokeStyle = '#00ff00';
            ctx.lineWidth = 2;
            ctx.beginPath();
            
            const steps = 1000;
            const dt = 2 * Math.PI / steps;
            let arcLength = 0;
            
            for (let i = 0; i <= steps; i++) {
                const ti = i * dt;
                const x = curve.x(ti);
                const y = curve.y(ti);
                const screen = toScreenCoords(x, y);
                
                if (i === 0) {
                    ctx.moveTo(screen.x, screen.y);
                } else {
                    ctx.lineTo(screen.x, screen.y);
                    
                    // Calculate arc length up to t0
                    if (ti <= t0 && showArcLength) {
                        const dx = curve.x(ti) - curve.x(ti - dt);
                        const dy = curve.y(ti) - curve.y(ti - dt);
                        arcLength += Math.sqrt(dx * dx + dy * dy);
                    }
                }
            }
            ctx.stroke();
            
            // Draw point at t0
            const x0 = curve.x(t0);
            const y0 = curve.y(t0);
            const screen0 = toScreenCoords(x0, y0);
            
            ctx.fillStyle = '#ff0000';
            ctx.fillRect(screen0.x - 4, screen0.y - 4, 8, 8);
            
            // Draw tangent line
            if (showTangent) {
                const dx = -Math.sin(t0); // derivative of cos(t)
                const dy = Math.cos(t0);  // derivative of sin(t)
                const slope = dy / dx;
                
                ctx.strokeStyle = '#ffff00';
                ctx.lineWidth = 2;
                ctx.beginPath();
                
                // Extend tangent line
                const extend = 2;
                const x1 = x0 - extend * dx / Math.sqrt(dx * dx + dy * dy);
                const y1 = y0 - extend * dy / Math.sqrt(dx * dx + dy * dy);
                const x2 = x0 + extend * dx / Math.sqrt(dx * dx + dy * dy);
                const y2 = y0 + extend * dy / Math.sqrt(dx * dx + dy * dy);
                
                const screen1 = toScreenCoords(x1, y1);
                const screen2 = toScreenCoords(x2, y2);
                
                ctx.moveTo(screen1.x, screen1.y);
                ctx.lineTo(screen2.x, screen2.y);
                ctx.stroke();
                
                // Update slope display
                document.getElementById('tangentSlope').textContent = slope.toFixed(3);
            }
            
            // Update arc length display
            document.getElementById('arcLength').textContent = arcLength.toFixed(3);
            
            animationFrames.parametricCalc = requestAnimationFrame(animateParametricCalc);
        }
        
        // Polar curve animation
        function animatePolar() {
            const ctx = contexts.polar;
            const theta = parseFloat(document.getElementById('thetaRange').value);
            const curve = polarCurves[polarType];
            
            ctx.clearRect(0, 0, 500, 400);
            drawGrid(ctx);
            
            // Draw curve
            ctx.strokeStyle = '#00ff00';
            ctx.lineWidth = 2;
            ctx.beginPath();
            
            const steps = 1000;
            const dtheta = theta / steps;
            
            for (let i = 0; i <= steps; i++) {
                const thetai = i * dtheta;
                const r = curve.r(thetai);
                const x = r * Math.cos(thetai);
                const y = r * Math.sin(thetai);
                const screen = toScreenCoords(x, y);
                
                if (i === 0) {
                    ctx.moveTo(screen.x, screen.y);
                } else {
                    ctx.lineTo(screen.x, screen.y);
                }
            }
            ctx.stroke();
            
            // Draw current point
            const currentR = curve.r(theta);
            const currentX = currentR * Math.cos(theta);
            const currentY = currentR * Math.sin(theta);
            const currentScreen = toScreenCoords(currentX, currentY);
            
            ctx.fillStyle = '#ff0000';
            ctx.fillRect(currentScreen.x - 4, currentScreen.y - 4, 8, 8);
            
            // Draw radius line
            ctx.strokeStyle = '#ffff00';
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.moveTo(250, 200);
            ctx.lineTo(currentScreen.x, currentScreen.y);
            ctx.stroke();
            
            animationFrames.polar = requestAnimationFrame(animatePolar);
        }
        
        // Polar calculus visualization
        function animatePolarCalc() {
            const ctx = contexts.polarCalc;
            const alpha = parseFloat(document.getElementById('alphaRange').value);
            const beta = parseFloat(document.getElementById('betaRange').value);
            const showArea = document.getElementById('showArea').checked;
            const curve = polarCurves.cardioid; // Using cardioid for calc demo
            
            ctx.clearRect(0, 0, 500, 400);
            drawGrid(ctx);
            
            // Draw full curve
            ctx.strokeStyle = '#00ff00';
            ctx.lineWidth = 2;
            ctx.beginPath();
            
            const steps = 1000;
            const dtheta = 2 * Math.PI / steps;
            
            for (let i = 0; i <= steps; i++) {
                const theta = i * dtheta;
                const r = curve.r(theta);
                const x = r * Math.cos(theta);
                const y = r * Math.sin(theta);
                const screen = toScreenCoords(x, y, 60);
                
                if (i === 0) {
                    ctx.moveTo(screen.x, screen.y);
                } else {
                    ctx.lineTo(screen.x, screen.y);
                }
            }
            ctx.stroke();
            
            // Draw and calculate area
            if (showArea && beta > alpha) {
                ctx.fillStyle = 'rgba(255, 0, 0, 0.3)';
                ctx.beginPath();
                ctx.moveTo(250, 200);
                
                const areaSteps = 100;
                const dtheta2 = (beta - alpha) / areaSteps;
                let area = 0;
                
                for (let i = 0; i <= areaSteps; i++) {
                    const theta = alpha + i * dtheta2;
                    const r = curve.r(theta);
                    const x = r * Math.cos(theta);
                    const y = r * Math.sin(theta);
                    const screen = toScreenCoords(x, y, 60);
                    ctx.lineTo(screen.x, screen.y);
                    
                    if (i > 0) {
                        area += 0.5 * r * r * dtheta2;
                    }
                }
                
                ctx.closePath();
                ctx.fill();
                
                // Update area display
                document.getElementById('polarArea').textContent = area.toFixed(3);
            }
            
            // Calculate arc length
            let arcLength = 0;
            if (beta > alpha) {
                const arcSteps = 100;
                const dtheta3 = (beta - alpha) / arcSteps;
                
                for (let i = 1; i <= arcSteps; i++) {
                    const theta = alpha + i * dtheta3;
                    const thetaPrev = alpha + (i - 1) * dtheta3;
                    const r = curve.r(theta);
                    const rPrev = curve.r(thetaPrev);
                    
                    // Approximate dr/dtheta
                    const dr = (r - rPrev) / dtheta3;
                    
                    arcLength += Math.sqrt(r * r + dr * dr) * dtheta3;
                }
                
                document.getElementById('polarArcLength').textContent = arcLength.toFixed(3);
            }
            
            animationFrames.polarCalc = requestAnimationFrame(animatePolarCalc);
        }
        
        // Control event listeners
        document.getElementById('tRange').addEventListener('input', (e) => {
            document.getElementById('tValue').textContent = `t = ${parseFloat(e.target.value).toFixed(2)}`;
        });
        
        document.getElementById('speedRange').addEventListener('input', (e) => {
            document.getElementById('speedValue').textContent = `Speed: ${parseFloat(e.target.value).toFixed(1)}x`;
        });
        
        document.getElementById('t0Range').addEventListener('input', (e) => {
            document.getElementById('t0Value').textContent = `t₀ = ${parseFloat(e.target.value).toFixed(2)}`;
        });
        
        document.getElementById('thetaRange').addEventListener('input', (e) => {
            document.getElementById('thetaValue').textContent = `θ = ${parseFloat(e.target.value).toFixed(2)}`;
        });
        
        document.getElementById('alphaRange').addEventListener('input', (e) => {
            document.getElementById('alphaValue').textContent = `α = ${parseFloat(e.target.value).toFixed(2)}`;
        });
        
        document.getElementById('betaRange').addEventListener('input', (e) => {
            document.getElementById('betaValue').textContent = `β = ${parseFloat(e.target.value).toFixed(2)}`;
        });
        
        // Example setters
        function setParametricExample(type) {
            parametricType = type;
            const curve = parametricCurves[type];
            document.getElementById('currentParametric').textContent = curve.name;
            document.getElementById('parametricEquations').textContent = curve.equations;
            document.getElementById('tRange').max = curve.tMax;
            document.getElementById('tRange').value = curve.tMax;
            document.getElementById('tValue').textContent = `t = ${curve.tMax.toFixed(2)}`;
        }
        
        function setPolarExample(type) {
            polarType = type;
            const curve = polarCurves[type];
            document.getElementById('currentPolar').textContent = curve.name;
            document.getElementById('polarEquation').textContent = curve.equation;
            document.getElementById('thetaRange').max = curve.thetaMax;
            document.getElementById('thetaRange').value = curve.thetaMax;
            document.getElementById('thetaValue').textContent = `θ = ${curve.thetaMax.toFixed(2)}`;
        }
        
        // Initialize canvas for active tab
        function initializeCanvas(tabId) {
            // Cancel all animations
            Object.values(animationFrames).forEach(frame => {
                if (frame) cancelAnimationFrame(frame);
            });
            
            // Start appropriate animation
            switch (tabId) {
                case 'parametric':
                    animateParametric();
                    break;
                case 'parametric-calc':
                    animateParametricCalc();
                    break;
                case 'polar':
                    animatePolar();
                    break;
                case 'polar-calc':
                    animatePolarCalc();
                    break;
            }
        }
        
        // Start with parametric tab
        initializeCanvas('parametric');
    </script>
</body>
</html>