- Sections and slides rewritten in Swedish; German law and institutions replaced by Swedish/CEPT/ITU equivalents (PTS, SSA, PTSFS 2025:1, SSMFS 2008:18), unverified statements marked "% TODO VERIFY" - New toc: INSTEG, HAREC, UPPGRADERING; section idents are Swedish (see ident-map.tsv) - Exam-question tags, BNetzA question pool, solutions and the German SWL course removed - Static pages, snippets, applets, READMEs and image alt-texts translated - TikZ labels translated; SVG drawings regenerated (drawing 689 still fails to build upstream: it references a missing photo) - Changed from the original: not endorsed by DARC e.V., SSA or PTS Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
160 lines
4.5 KiB
HTML
160 lines
4.5 KiB
HTML
<html>
|
|
<script src="https://www.50ohm.de/assets/jquery/3.7.1/jquery.min.js"></script>
|
|
<script src="https://www.50ohm.de/assets/chartjs/4.4.1/chart.min.js"></script>
|
|
|
|
<p>Här kan du undersöka Fourierapproximationen av en symmetrisk fyrkantsignal med ett valbart antal udda övertoner. Reglagen tillåter värden från 1 till 500.</p>
|
|
|
|
<table>
|
|
<tr>
|
|
<td>Övertoner $N$:</td>
|
|
<td>
|
|
<input type="range" id="harmonicsRange" min="1" max="499" value="1" step="2">
|
|
</td>
|
|
<td>
|
|
<input type="number" id="harmonicsInput" min="1" max="499" value="1" step="2" style="width: 6em;">
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<canvas id="rectangleFourierChart" style="width:100%; height:260px;"></canvas>
|
|
|
|
<script>
|
|
const chartCanvas = document.getElementById('rectangleFourierChart');
|
|
const harmonicsRange = document.getElementById('harmonicsRange');
|
|
const harmonicsInput = document.getElementById('harmonicsInput');
|
|
const xMin = -1.5 * Math.PI;
|
|
const xMax = 1.5 * Math.PI;
|
|
|
|
const rectangleChart = new Chart(chartCanvas, {
|
|
type: 'line',
|
|
data: {
|
|
datasets: [
|
|
{
|
|
label: 'Fyrkant, ideal',
|
|
borderColor: '#ED7D71',
|
|
backgroundColor: 'transparent',
|
|
pointRadius: 0,
|
|
borderDash: [6, 4],
|
|
data: []
|
|
},
|
|
{
|
|
label: 'Fourierapproximation',
|
|
borderColor: '#00AEDF',
|
|
backgroundColor: 'transparent',
|
|
pointRadius: 0,
|
|
tension: 0.15,
|
|
data: []
|
|
}
|
|
]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
animation: false,
|
|
plugins: {
|
|
legend: {
|
|
display: true
|
|
}
|
|
},
|
|
scales: {
|
|
x: {
|
|
type: 'linear',
|
|
min: xMin,
|
|
max: xMax,
|
|
title: {
|
|
display: true,
|
|
text: 't'
|
|
},
|
|
ticks: {
|
|
callback: function(value) {
|
|
if (Math.abs(value) < 1e-8) return '0';
|
|
if (Math.abs(value - Math.PI) < 1e-8) return 'π';
|
|
if (Math.abs(value + Math.PI) < 1e-8) return '-π';
|
|
if (Math.abs(value - 1.5 * Math.PI) < 1e-8) return '3π/2';
|
|
if (Math.abs(value + 1.5 * Math.PI) < 1e-8) return '-3π/2';
|
|
return value.toFixed(2).replace(".", ",");
|
|
}
|
|
}
|
|
},
|
|
y: {
|
|
min: -1.3,
|
|
max: 1.3,
|
|
title: {
|
|
display: true,
|
|
text: 'f(t)'
|
|
},
|
|
ticks: {
|
|
stepSize: 0.5,
|
|
callback: function(value) {
|
|
return value.toFixed(1).replace(".", ",");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
function clampHarmonics(value) {
|
|
const parsed = Number.parseInt(value, 10);
|
|
if (Number.isNaN(parsed)) return 1;
|
|
const clamped = Math.max(1, Math.min(499, parsed));
|
|
return clamped % 2 === 0 ? clamped - 1 : clamped;
|
|
}
|
|
|
|
function buildFourierSeries(n) {
|
|
const samples = [];
|
|
const sampleCount = Math.max(1200, n * 40);
|
|
const step = (xMax - xMin) / sampleCount;
|
|
|
|
for (let x = xMin; x <= xMax + 1e-9; x += step) {
|
|
let y = 0;
|
|
for (let k = 1; k <= n; k += 2) {
|
|
y += (4 / Math.PI) * Math.sin(k * x) / k;
|
|
}
|
|
samples.push({ x, y });
|
|
}
|
|
|
|
const idealPoints = [
|
|
{ x: xMin, y: 1 },
|
|
{ x: -Math.PI, y: 1 },
|
|
{ x: -Math.PI, y: -1 },
|
|
{ x: 0, y: -1 },
|
|
{ x: 0, y: 1 },
|
|
{ x: Math.PI, y: 1 },
|
|
{ x: Math.PI, y: -1 },
|
|
{ x: xMax, y: -1 }
|
|
];
|
|
|
|
return { samples, idealPoints };
|
|
}
|
|
|
|
function updateChart() {
|
|
const n = clampHarmonics(harmonicsInput.value);
|
|
harmonicsRange.value = n;
|
|
harmonicsInput.value = n;
|
|
|
|
const { samples, idealPoints } = buildFourierSeries(n);
|
|
|
|
rectangleChart.data.datasets[0].data = idealPoints.map(point => ({ x: point.x, y: point.y }));
|
|
rectangleChart.data.datasets[1].data = samples.map(point => ({ x: point.x, y: point.y }));
|
|
rectangleChart.update();
|
|
}
|
|
|
|
harmonicsRange.addEventListener('input', function() {
|
|
harmonicsInput.value = this.value;
|
|
updateChart();
|
|
});
|
|
|
|
harmonicsInput.addEventListener('input', function() {
|
|
harmonicsRange.value = this.value;
|
|
updateChart();
|
|
});
|
|
|
|
harmonicsInput.addEventListener('change', function() {
|
|
harmonicsRange.value = this.value;
|
|
updateChart();
|
|
});
|
|
|
|
updateChart();
|
|
</script>
|
|
</html>
|