Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { useState, useEffect, useRef } from 'react';
- const TrojfazoveNapatiaAPrudy = () => {
- const [time, setTime] = useState(0);
- const [frequency, setFrequency] = useState(50);
- const [speed, setSpeed] = useState(1);
- const [voltageAmplitude, setVoltageAmplitude] = useState(325);
- const [currentAmplitude, setCurrentAmplitude] = useState(91.92);
- const [powerFactor, setPowerFactor] = useState(0.89);
- const [loadType, setLoadType] = useState('R');
- const [visibleWaves, setVisibleWaves] = useState({
- L1: true, L2: true, L3: true,
- I1: true, I2: true, I3: true
- });
- const [showPhasorDiagram, setShowPhasorDiagram] = useState(false);
- const animationRef = useRef();
- const width = 800;
- const height = 850;
- const margin = { top: 20, right: 180, bottom: 50, left: 60 };
- const chartWidth = width - margin.left - margin.right;
- const chartHeight = (height - margin.top - margin.bottom - 250) / 2;
- const xScale = (t) => (t / 0.04) * chartWidth;
- const yScaleVoltage = (v) => chartHeight / 2 - (v / (voltageAmplitude * 1.2)) * (chartHeight / 2);
- const yScaleCurrent = (i) => chartHeight / 2 - (i / (currentAmplitude * 1.2)) * (chartHeight / 2);
- useEffect(() => {
- const animate = () => {
- setTime((prevTime) => (prevTime + 0.0005 * speed) % 0.04);
- animationRef.current = requestAnimationFrame(animate);
- };
- animationRef.current = requestAnimationFrame(animate);
- return () => cancelAnimationFrame(animationRef.current);
- }, [speed]);
- const calculatePhaseShift = () => {
- const phaseAngle = Math.acos(powerFactor);
- switch (loadType) {
- case 'R': return 0;
- case 'L': return -phaseAngle;
- case 'C': return phaseAngle;
- default: return 0;
- }
- };
- const phaseShift = calculatePhaseShift();
- const generatePath = (amplitude, phase, yScale, isVoltage) => {
- let path = `M ${xScale(0)} ${yScale(amplitude * Math.sin(2 * Math.PI * frequency * time + phase + (isVoltage ? 0 : phaseShift)))}`;
- for (let t = 0.0001; t <= 0.04; t += 0.0001) {
- const x = xScale(t);
- const y = yScale(amplitude * Math.sin(2 * Math.PI * frequency * (t + time) + phase + (isVoltage ? 0 : phaseShift)));
- path += ` L ${x} ${y}`;
- }
- return path;
- };
- const phases = [
- { name: 'L1', color: '#FF0000', phase: 0 },
- { name: 'L2', color: '#00FF00', phase: -2 * Math.PI / 3 },
- { name: 'L3', color: '#0000FF', phase: 2 * Math.PI / 3 },
- ];
- const rmsVoltage = (voltageAmplitude / Math.sqrt(2)).toFixed(2);
- const rmsCurrent = (currentAmplitude / Math.sqrt(2)).toFixed(2);
- const renderChart = (yScale, amplitude, title, unit, isVoltage = true) => (
- <g>
- <text x={chartWidth / 2} y={-10} textAnchor="middle" fontWeight="bold">{title}</text>
- {/* Grid */}
- {Array.from({length: 9}, (_, i) => i * chartHeight / 8).map(y => (
- <line key={y} x1={0} y1={y} x2={chartWidth} y2={y} stroke="#ddd" strokeDasharray="3,3" />
- ))}
- {Array.from({length: 9}, (_, i) => i * chartWidth / 8).map(x => (
- <line key={x} x1={x} y1={0} x2={x} y2={chartHeight} stroke="#ddd" strokeDasharray="3,3" />
- ))}
- {/* X-axis */}
- <line x1={0} y1={chartHeight} x2={chartWidth} y2={chartHeight} stroke="black" />
- {[0, 0.01, 0.02, 0.03, 0.04].map((tick) => (
- <g key={tick} transform={`translate(${xScale(tick)},${chartHeight})`}>
- <line y2={5} stroke="black" />
- <text y={20} textAnchor="middle">{tick.toFixed(2)}</text>
- </g>
- ))}
- {/* Y-axis */}
- <line x1={0} y1={0} x2={0} y2={chartHeight} stroke="black" />
- {[-amplitude, -amplitude/2, 0, amplitude/2, amplitude].map((tick) => (
- <g key={tick} transform={`translate(0,${yScale(tick)})`}>
- <line x2={-5} stroke="black" />
- <text x={-10} dy=".32em" textAnchor="end">{tick.toFixed(0)}</text>
- </g>
- ))}
- <text transform={`rotate(-90) translate(-${chartHeight / 2},${-margin.left + 20})`} textAnchor="middle">{unit}</text>
- {/* Waveforms */}
- {phases.map(({ color, phase, name }) => (
- visibleWaves[isVoltage ? name : `I${name.slice(1)}`] && (
- <path
- key={name}
- d={generatePath(amplitude, phase, yScale, isVoltage)}
- fill="none"
- stroke={color}
- strokeWidth="2"
- />
- )
- ))}
- </g>
- );
- const renderPhasorDiagram = () => {
- const centerX = chartWidth / 2;
- const centerY = chartHeight / 2;
- const radius = Math.min(centerX, centerY) * 0.8;
- const drawPhasor = (angle, length, color, label) => {
- const x = centerX + length * Math.cos(angle);
- const y = centerY - length * Math.sin(angle);
- return (
- <g key={label}>
- <line x1={centerX} y1={centerY} x2={x} y2={y} stroke={color} strokeWidth="2" />
- <text x={x + 10 * Math.cos(angle)} y={y - 10 * Math.sin(angle)} fill={color}>{label}</text>
- </g>
- );
- };
- return (
- <g>
- <circle cx={centerX} cy={centerY} r={radius} stroke="#ddd" fill="none" />
- {phases.map(({ name, color, phase }) => (
- <React.Fragment key={name}>
- {drawPhasor(phase, radius, color, `U${name.slice(1)}`)}
- {drawPhasor(phase + phaseShift, radius * currentAmplitude / voltageAmplitude, color, `I${name.slice(1)}`)}
- </React.Fragment>
- ))}
- </g>
- );
- };
- const toggleWave = (wave) => {
- setVisibleWaves(prev => ({ ...prev, [wave]: !prev[wave] }));
- };
- return (
- <div>
- <h2 style={{ textAlign: 'center' }}>Trojfázové striedavé napätia a prúdy s fázorovým diagramom</h2>
- <div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', marginBottom: '10px', gap: '20px' }}>
- <label>
- Frekvencia (Hz):
- <input
- type="number"
- value={frequency}
- onChange={(e) => setFrequency(Number(e.target.value))}
- min="1"
- max="100"
- step="1"
- />
- </label>
- <div>
- <label htmlFor="speedSlider">Rýchlosť animácie: {speed.toFixed(2)}x</label>
- <input
- id="speedSlider"
- type="range"
- min="0"
- max="2"
- step="0.01"
- value={speed}
- onChange={(e) => setSpeed(Number(e.target.value))}
- style={{ width: '200px' }}
- />
- </div>
- <div>
- <label htmlFor="voltageSlider">Amplitúda napätia: {voltageAmplitude.toFixed(0)} V</label>
- <input
- id="voltageSlider"
- type="range"
- min="100"
- max="500"
- step="1"
- value={voltageAmplitude}
- onChange={(e) => setVoltageAmplitude(Number(e.target.value))}
- style={{ width: '200px' }}
- />
- </div>
- <div>
- <label htmlFor="currentSlider">Amplitúda prúdu: {currentAmplitude.toFixed(2)} A</label>
- <input
- id="currentSlider"
- type="range"
- min="10"
- max="200"
- step="0.1"
- value={currentAmplitude}
- onChange={(e) => setCurrentAmplitude(Number(e.target.value))}
- style={{ width: '200px' }}
- />
- </div>
- <div>
- <label htmlFor="powerFactorSlider">Účinník: {powerFactor.toFixed(2)}</label>
- <input
- id="powerFactorSlider"
- type="range"
- min="0"
- max="1"
- step="0.01"
- value={powerFactor}
- onChange={(e) => setPowerFactor(Number(e.target.value))}
- style={{ width: '200px' }}
- />
- </div>
- <div>
- <label>Typ záťaže:</label>
- <select value={loadType} onChange={(e) => setLoadType(e.target.value)}>
- <option value="R">Odporová (R)</option>
- <option value="L">Induktívna (L)</option>
- <option value="C">Kapacitná (C)</option>
- </select>
- </div>
- <div>
- <label>
- <input
- type="checkbox"
- checked={showPhasorDiagram}
- onChange={() => setShowPhasorDiagram(!showPhasorDiagram)}
- />
- Zobraziť fázorový diagram
- </label>
- </div>
- </div>
- <svg width={width} height={height}>
- <g transform={`translate(${margin.left},${margin.top})`}>
- {showPhasorDiagram ? (
- renderPhasorDiagram()
- ) : (
- <>
- {renderChart(yScaleVoltage, voltageAmplitude, "Napätie", "Napätie (V)", true)}
- <g transform={`translate(0,${chartHeight + margin.top})`}>
- {renderChart(yScaleCurrent, currentAmplitude, "Prúd", "Prúd (A)", false)}
- </g>
- </>
- )}
- {/* Legend and toggles */}
- <g transform={`translate(${chartWidth + 10}, 0)`}>
- {phases.map(({ name, color }, index) => (
- <g key={name} transform={`translate(0, ${index * 40})`}>
- <rect width={15} height={15} fill={color} />
- <text x={20} y={12}>{name}</text>
- <foreignObject x="0" y="20" width="100" height="20">
- <label style={{ fontSize: '12px' }}>
- <input
- type="checkbox"
- checked={visibleWaves[name]}
- onChange={() => toggleWave(name)}
- />
- Zobraziť
- </label>
- </foreignObject>
- </g>
- ))}
- {phases.map(({ name, color }, index) => (
- <g key={`I${name}`} transform={`translate(0, ${(index + 3) * 40})`}>
- <rect width={15} height={15} fill={color} />
- <text x={20} y={12}>{`I${name.slice(1)}`}</text>
- <foreignObject x="0" y="20" width="100" height="20">
- <label style={{ fontSize: '12px' }}>
- <input
- type="checkbox"
- checked={visibleWaves[`I${name.slice(1)}`]}
- onChange={() => toggleWave(`I${name.slice(1)}`)}
- />
- Zobraziť
- </label>
- </foreignObject>
- </g>
- ))}
- </g>
- {/* Key values */}
- <g transform={`translate(${chartWidth + 10}, ${chartHeight * 2 + margin.top * 2})`}>
- <text y="20">RMS Napätie: {rmsVoltage} V</text>
- <text y="40">RMS Prúd: {rmsCurrent} A</text>
- <text y="60">Frekvencia: {frequency} Hz</text>
- <text y="80">Typ záťaže: {loadType === 'R' ? 'Odporová' : loadType === 'L' ? 'Induktívna' : 'Kapacitná'}</text>
- <text y="100">Účinník: {powerFactor.toFixed(2)}</text>
- <text y="120">Fázový posun: {(phaseShift * 180 / Math.PI).toFixed(2)}°</text>
- </g>
- </g>
- </svg>
- </div>
- );
- };
- export default TrojfazoveNapatiaAPrudy;
Advertisement
Add Comment
Please, Sign In to add comment