From 2ecc0c93e252d3d5260b6af5a2fb696d8c43dc4f Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 23 Jun 2026 17:17:09 +0300 Subject: [PATCH] feat: web beacon marker as two-half filter (Manchester lobes) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the single tracked-beacon line with a filter band spanning the beacon width, split into two halves (left/right Manchester lobes at ±400 Hz) with a central divider (carrier null) and band edges at ±450 Hz, matching the desktop dec-marker width. Reference frequency is now a green dashed line. Frontend only (WebPageHtml). Co-Authored-By: Claude Opus 4.8 --- WebPageHtml.pas | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/WebPageHtml.pas b/WebPageHtml.pas index c1b51e9..4607ad4 100644 --- a/WebPageHtml.pas +++ b/WebPageHtml.pas @@ -748,11 +748,22 @@ begin 'function drawMk(ctx,w,h){if(!markerOn)return;ctx.save();ctx.strokeStyle="rgba(255,80,80,.85)";ctx.lineWidth=1;ctx.beginPath();ctx.moveTo(markerX,0);ctx.lineTo(markerX,h);ctx.stroke();' + 'const lbl=((xToHz(markerX,w))/1e6).toFixed(4)+" M";ctx.fillStyle="rgba(35,5,5,.82)";ctx.fillRect(cl(markerX+5,0,w-88),h-16,84,13);ctx.fillStyle="#f88";ctx.font="10px monospace";ctx.fillText(lbl,cl(markerX+8,2,w-86),h-6);ctx.restore();}' + - // Маркеры QO-100 маяка: опорная (зелёная) + измеренная/наведение (оранжевая). - 'function vbar(ctx,x,w,h,col){if(x<0||x>w)return;ctx.strokeStyle=col;ctx.lineWidth=1;ctx.beginPath();ctx.moveTo(x+.5,0);ctx.lineTo(x+.5,h);ctx.stroke();}' + + // Маркеры QO-100 маяка: опорная (зелёная пунктир) + ФИЛЬТР по ширине маяка из + // ДВУХ ПОЛОВИНОК (две несущие/лепестка Manchester ±400Гц, нуль по центру). + 'var BCN_HALF=450;' + // полуширина фильтра маяка, Гц (как десктоп dec-маркер) + 'function vbar(ctx,x,h,col,w){if(x<0||x>w)return;ctx.strokeStyle=col;ctx.lineWidth=1;ctx.beginPath();ctx.moveTo(x+.5,0);ctx.lineTo(x+.5,h);ctx.stroke();}' + 'function drawBcn(ctx,w,h){if(!cur.beacon_on)return;ctx.save();' + - 'if(cur.beacon_ref_hz>0)vbar(ctx,hzToX(cur.beacon_ref_hz,w),w,h,"rgba(80,255,120,.8)");' + - 'if(cur.beacon_track_hz>0)vbar(ctx,hzToX(cur.beacon_track_hz,w),w,h,"rgba(255,170,60,.85)");' + + // Опорная — где маяк ДОЛЖЕН быть. + 'if(cur.beacon_ref_hz>0){ctx.setLineDash([4,3]);vbar(ctx,hzToX(cur.beacon_ref_hz,w),h,"rgba(80,255,120,.85)",w);ctx.setLineDash([]);}' + + // Фильтр маяка вокруг измеренной частоты: левая+правая половины (лепестки) с + // разделом по центру (нуль несущей) и гранями полосы. + 'var t=cur.beacon_track_hz;' + + 'if(t>0){var xL=hzToX(t-BCN_HALF,w),xC=hzToX(t,w),xR=hzToX(t+BCN_HALF,w);' + + 'ctx.fillStyle="rgba(255,170,60,.14)";' + + 'ctx.fillRect(xL,0,Math.max(0,xC-xL-1),h);' + // левая половина + 'ctx.fillRect(xC+1,0,Math.max(0,xR-xC-1),h);' + // правая половина + 'vbar(ctx,xL,h,"rgba(255,170,60,.75)",w);vbar(ctx,xR,h,"rgba(255,170,60,.75)",w);' + // грани + 'vbar(ctx,xC,h,"rgba(255,170,60,.4)",w);}' + // центр (нуль/раздел) 'ctx.restore();}' + 'function drawRuler(){const w=rulerCv.clientWidth,h=rulerCv.clientHeight;rctx.fillStyle="#0c1210";rctx.fillRect(0,0,w,h);' +