fixed gistogramm

This commit is contained in:
2026-06-17 11:22:15 +03:00
parent 920a839197
commit f4ef87705c
3 changed files with 16 additions and 114 deletions
+1 -87
View File
@@ -1,91 +1,7 @@
/** Polar rose and quality-vs-distance charts for TX/RX track compare. */
/** RX quality vs distance chart for TX/RX track compare. */
(function (global) {
'use strict';
function bearingDeg(lat1, lon1, lat2, lon2) {
const toRad = d => d * Math.PI / 180;
const toDeg = r => r * 180 / Math.PI;
const dLon = toRad(lon2 - lon1);
const y = Math.sin(dLon) * Math.cos(toRad(lat2));
const x = Math.cos(toRad(lat1)) * Math.sin(toRad(lat2))
- Math.sin(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.cos(dLon);
return (toDeg(Math.atan2(y, x)) + 360) % 360;
}
function drawQualityRose(canvas, samples, qualityColor) {
if (!canvas) return;
const ctx = canvas.getContext('2d');
const w = canvas.clientWidth || 140;
const h = canvas.clientHeight || 140;
if (canvas.width !== w) canvas.width = w;
if (canvas.height !== h) canvas.height = h;
ctx.fillStyle = '#0a0a14';
ctx.fillRect(0, 0, w, h);
const sectors = 16;
const cx = w / 2;
const cy = h / 2;
const maxR = Math.min(w, h) * 0.38;
if (!samples?.length) {
ctx.fillStyle = '#888';
ctx.font = '11px system-ui';
ctx.textAlign = 'center';
ctx.fillText('нет данных качества', cx, cy);
return;
}
const bins = Array.from({ length: sectors }, () => ({ sum: 0, count: 0 }));
const step = 360 / sectors;
for (const s of samples) {
const idx = Math.floor(((s.bearing % 360) + 360) % 360 / step) % sectors;
bins[idx].sum += s.quality;
bins[idx].count += 1;
}
const maxCount = Math.max(1, ...bins.map(b => b.count));
ctx.strokeStyle = '#333';
ctx.beginPath();
ctx.arc(cx, cy, maxR, 0, Math.PI * 2);
ctx.stroke();
for (let i = 0; i < sectors; i++) {
const start = (i * step - 90) * Math.PI / 180;
const end = ((i + 1) * step - 90) * Math.PI / 180;
const b = bins[i];
if (!b.count) continue;
const avgQ = b.sum / b.count;
const r = maxR * (0.15 + 0.85 * (b.count / maxCount));
const col = qualityColor ? qualityColor(avgQ) : '#888';
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.arc(cx, cy, r, start, end);
ctx.closePath();
ctx.fillStyle = col;
ctx.globalAlpha = 0.85;
ctx.fill();
ctx.globalAlpha = 1;
ctx.strokeStyle = '#222';
ctx.lineWidth = 0.5;
ctx.stroke();
}
ctx.fillStyle = '#aaa';
ctx.font = '9px system-ui';
ctx.textAlign = 'center';
ctx.fillText('N', cx, cy - maxR - 4);
ctx.fillText('S', cx, cy + maxR + 10);
ctx.textAlign = 'left';
ctx.fillText('E', cx + maxR + 4, cy + 3);
ctx.textAlign = 'right';
ctx.fillText('W', cx - maxR - 4, cy + 3);
ctx.fillStyle = '#888';
ctx.font = '8px system-ui';
ctx.textAlign = 'center';
ctx.fillText('длина ∝ число точек', cx, h - 4);
}
function drawQualityDistChart(canvas, samples, qualityColor, highlightDist) {
if (!canvas) return;
const ctx = canvas.getContext('2d');
@@ -175,8 +91,6 @@
}
global.QualityViz = {
bearingDeg,
drawQualityRose,
drawQualityDistChart,
};
})(typeof window !== 'undefined' ? window : globalThis);